1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2
3 /* AbiWord
4 * Copyright (C) 1998 AbiSource, Inc.
5 * Copyright (c) 2001,2002 Tomas Frydrych
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301 USA.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27
28
29 #include "fp_Run.h"
30 #include "fp_TextRun.h"
31 #include "fl_DocLayout.h"
32 #include "fl_BlockLayout.h"
33 #include "fp_Line.h"
34
35 #include "fp_Column.h"
36 #include "fp_Page.h"
37 #include "pp_Property.h"
38 #include "gr_Graphics.h"
39 #include "pd_Document.h"
40 #include "gr_DrawArgs.h"
41 #include "pp_AttrProp.h"
42 #include "fd_Field.h"
43 #include "po_Bookmark.h"
44 #include "ut_debugmsg.h"
45 #include "ut_assert.h"
46 #include "ut_string.h"
47 #include "ut_std_string.h"
48 #include "ut_growbuf.h"
49 #include "ut_go_file.h"
50 #include "fp_TableContainer.h"
51 #include "fl_TableLayout.h"
52 #include "fl_FootnoteLayout.h"
53 #include "fp_FootnoteContainer.h"
54 #include "fl_AutoNum.h"
55 #include "fv_View.h"
56 #include "fl_TOCLayout.h"
57 #include "ap_Prefs.h"
58 #include "ap_Strings.h"
59 #include "xap_App.h"
60 #include "xap_Frame.h"
61 #include "gr_Painter.h"
62
63 #include "ut_sleep.h"
64
65 // define this if you want fp_Run::lookupProperties() to dump props and attr belonging to
66 // this run. NB this has a very adverse effect on performance, so it should be turned off
67 // before committing
68 //#define FPRUN_PROPS_MINI_DUMP
69
70 // TODO can we use the indexAP provided in the change records
71 // TODO to remember the attr/prop for each run rather than
72 // TODO looking it up each time we call lookupProperties() -- jeff 4/19/99
73
74
75 // findPointCoords:
76 // Can be called to find the position and size of the point (cursor)
77 // for an offset both before, inside and after the Run.
78 // Before: When the Run is the first on a Line and point is a BOL.
79 // Inside: When the point is inside the Run.
80 // After : Point is at the start of the next Run, but insertion is
81 // done with the properties of this Run so cursor size/position
82 // must reflect that.
83 //
84 // Previous implementations would assert that the offset was within the
85 // Run, but that would always fail for the 'After' case.
86
87 /*****************************************************************/
88
89 /*
90 TODO this file is too long -- it needs to be broken
91 up into several pieces.
92 */
93
fp_Run(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen,FP_RUN_TYPE iType)94 fp_Run::fp_Run(fl_BlockLayout* pBL,
95 UT_uint32 iOffsetFirst,
96 UT_uint32 iLen,
97 FP_RUN_TYPE iType) :
98 fp_ContainerObject(FP_CONTAINER_RUN, pBL->getSectionLayout()),
99 m_iType (iType),
100 m_pLine(0),
101 m_pBL(pBL),
102 m_pNext(0),
103 m_pPrev(0),
104 m_iX(0),
105 m_iOldX(0),
106 m_iY(0),
107 m_iWidth(0),
108 m_iHeight(0),
109 m_iAscent(0),
110 m_iDescent(0),
111 m_iOffsetFirst(iOffsetFirst),
112 m_iLen(iLen),
113 m_bDirty(true), // a run which has just been created is not onscreen, therefore it is dirty
114 m_pField(0),
115 m_iDirection(UT_BIDI_WS), //by default all runs are whitespace
116 m_iVisDirection(UT_BIDI_UNSET),
117 m_eRefreshDrawBuffer(GRSR_Unknown), // everything
118 m_pColorHL(255,255,255,true), // set highlight colour to transparent
119 m_pFont(0),
120 m_bRecalcWidth(false),
121 m_fDecorations(0),
122 m_iLineWidth(0),
123 m_iLinethickness(0),
124 m_iUnderlineXoff(0),
125 m_imaxUnderline(0),
126 m_iminOverline(0),
127 m_iOverlineXoff(0),
128 m_pHyperlink(0),
129 m_pRevisions(NULL),
130 m_eVisibility(FP_VISIBLE),
131 m_bIsCleared(true),
132 m_FillType(NULL,this,FG_FILL_TRANSPARENT),
133 m_bPrinting(false),
134 m_iTmpX(0),
135 m_iTmpY(0),
136 m_iTmpWidth(0),
137 m_pTmpLine(NULL),
138 m_bDrawSelection(false),
139 m_iSelLow(0),
140 m_iSelHigh(0),
141 m_bMustClearScreen(false),
142 m_iAuthorColor(0)
143 #ifdef DEBUG
144 ,m_iFontAllocNo(0)
145 #endif
146 {
147 xxx_UT_DEBUGMSG(("fp_Run %x created!!! \n",this));
148 pBL->setPrevListLabel(false);
149 m_FillType.setDocLayout(m_pBL->getDocLayout());
150 }
151
~fp_Run()152 fp_Run::~fp_Run()
153 {
154 // no impl.
155 xxx_UT_DEBUGMSG(("~fp_Run %x deleted!!! \n",this));
156
157 // Zero these to trap mem errors.
158 #if 1
159 m_pPrev = NULL;
160 m_pNext = NULL;
161 m_pBL = NULL;
162 m_pLine = NULL;
163 #endif
164
165 DELETEP(m_pRevisions);
166 }
167
getHeight() const168 UT_sint32 fp_Run::getHeight() const
169 {
170 if(isHidden() == FP_VISIBLE)
171 {
172 return m_iHeight;
173 }
174 return 0;
175 }
176
getWidth() const177 UT_sint32 fp_Run::getWidth() const
178 {
179 if(isHidden() == FP_VISIBLE)
180 return m_iWidth;
181
182 return 0;
183 }
184
getAscent() const185 UT_uint32 fp_Run::getAscent() const
186 {
187 if(isHidden() == FP_VISIBLE)
188 {
189 FL_DocLayout * pLayout = getBlock()->getDocLayout();
190 if(getGraphics() && pLayout->isQuickPrint() && getGraphics()->queryProperties(GR_Graphics::DGP_PAPER) && (getType() != FPRUN_IMAGE) && (getType() != FPRUN_TEXT)&& (getType() != FPRUN_FIELD))
191 {
192 return static_cast<UT_uint32>(static_cast<double>(m_iAscent)*getGraphics()->getResolutionRatio());
193 }
194 return m_iAscent;
195 }
196 return 0;
197 }
198
getDescent() const199 UT_uint32 fp_Run::getDescent() const
200 {
201 if(isHidden() == FP_VISIBLE)
202 {
203 FL_DocLayout * pLayout = getBlock()->getDocLayout();
204 if(getGraphics() && pLayout->isQuickPrint() && getGraphics()->queryProperties(GR_Graphics::DGP_PAPER))
205 {
206 return static_cast<UT_uint32>(static_cast<double>(m_iDescent)*getGraphics()->getResolutionRatio());
207 }
208 return m_iDescent;
209 }
210
211 return 0;
212 }
213
getDrawingWidth() const214 UT_sint32 fp_Run::getDrawingWidth() const
215 {
216 if(isHidden() == FP_VISIBLE)
217 return static_cast<UT_sint32>(m_iWidth);
218
219 return 0;
220 }
221
222
getFillType(void)223 fg_FillType & fp_Run::getFillType(void)
224 {
225 return m_FillType;
226 }
227
getFillType(void) const228 const fg_FillType & fp_Run::getFillType(void) const
229 {
230 return m_FillType;
231 }
232
isInSelectedTOC(void)233 bool fp_Run::isInSelectedTOC(void)
234 {
235 if(getBlock()->isContainedByTOC())
236 {
237 fl_TOCLayout * pTOCL = static_cast<fl_TOCLayout *>(getBlock()->myContainingLayout());
238 return pTOCL->isSelected();
239 }
240 else
241 {
242 return false;
243 }
244
245 }
246
247 /*!
248 * The following are methods to avoid flickering while changing a selection.
249 * The idea is to generate a cliprect around just the selected text.
250 */
251
252 /*!
253 * Set the selection draw mode.
254 */
setSelectionMode(PT_DocPosition posLow,PT_DocPosition posHigh)255 void fp_Run::setSelectionMode(PT_DocPosition posLow, PT_DocPosition posHigh)
256 {
257 m_bDrawSelection = true;
258 m_iSelLow = posLow;
259 m_iSelHigh = posHigh;
260 }
261
262 /*!
263 * Clear the selection mode
264 */
clearSelectionMode(void)265 void fp_Run::clearSelectionMode(void)
266 {
267 m_bDrawSelection = false;
268 m_iSelLow = 0;
269 m_iSelHigh = 0;
270 }
271
isSelectionDraw(void) const272 bool fp_Run::isSelectionDraw(void) const
273 {
274 return m_bDrawSelection;
275 }
276
posSelLow(void) const277 PT_DocPosition fp_Run::posSelLow(void) const
278 {
279 return m_iSelLow;
280 }
281
posSelHigh(void) const282 PT_DocPosition fp_Run::posSelHigh(void) const
283 {
284 return m_iSelHigh;
285 }
286 /*!
287 * This method looks at the values of TmpX and TmpWidth and compares them
288 * to the new ones. If they're different we do a clearscreen on them.
289 */
clearIfNeeded(void)290 bool fp_Run::clearIfNeeded(void)
291 {
292 // only do this on runs that have not been cleared already
293 // see bug 8154
294 if(m_bIsCleared &&!getMustClearScreen() )
295 return true;
296
297 // if((getTmpX() == getX()) && (getTmpWidth() == getWidth()) && (getTmpY() == getY()))
298 if((getTmpX() == getX()) && (getTmpY() == getY()) && (getTmpLine() == getLine()) && !getMustClearScreen() )
299 {
300 return true;
301 }
302 if(getTmpLine() && (getLine() != getTmpLine()))
303 {
304 fp_Line * pTmpLine = getTmpLine();
305 UT_sint32 i = getBlock()->findLineInBlock(pTmpLine);
306 if(i < 0)
307 {
308 markWidthDirty();
309 return false;
310 }
311 fp_Run * pLastRun = pTmpLine->getLastRun();
312 pTmpLine->clearScreenFromRunToEnd(pLastRun);
313 markWidthDirty();
314 return false;
315 }
316 UT_sint32 iWidth = getWidth();
317 UT_sint32 iX = getX();
318 UT_sint32 iY = getY();
319 _setWidth(getTmpWidth());
320 //
321 // Special case of merging the first char into the first run of
322 // block
323 //
324 if(getMustClearScreen() && (getTmpWidth() == 0) && (getX() == getTmpX()))
325 _setWidth(iWidth);
326 _setX(getTmpX());
327 _setY(getTmpY());
328 //
329 // If a run was created by "split" it initially has X value zero. Don't
330 // reset the "clear" in this.
331 //
332 // If the run was just newly inserted (and is, therefore, not on screen) do not reset
333 // its clear flag
334 //
335 if(getTmpX() != 0 && getTmpWidth() != 0)
336 {
337 m_bIsCleared = false;
338 }
339 clearScreen();
340 markWidthDirty();
341 _setX(iX);
342 _setWidth(iWidth);
343 _setY(iY);
344 return false;
345 }
Fill(GR_Graphics * pG,UT_sint32 x,UT_sint32 y,UT_sint32 width,UT_sint32 height)346 void fp_Run::Fill(GR_Graphics * pG, UT_sint32 x, UT_sint32 y, UT_sint32 width,
347 UT_sint32 height)
348 {
349 xxx_UT_DEBUGMSG(("-------------------Fill called!!!!---- x %d width %d \n",x,width));
350 if((width < 1) || (height < 1))
351 {
352 return;
353 }
354 if(y < -9999999)
355 {
356 // Whoops! object is offscreen!
357 // Bailout
358 return;
359 }
360 UT_sint32 srcX = 0;
361 UT_sint32 srcY = 0;
362 fp_Line * pLine = getLine();
363 UT_sint32 xoff=0,yoff=0;
364 if(pLine)
365 {
366 pLine->getScreenOffsets(this,xoff,yoff);
367 fp_Page * pPage = pLine->getPage();
368 srcX = x - xoff;
369 if(pPage)
370 {
371 pPage->expandDamageRect(xoff+getX()+srcX,yoff+getY(),width,height);
372 }
373 }
374 bool bDoGrey = (pG->queryProperties(GR_Graphics::DGP_SCREEN) &&
375 ((getType() == FPRUN_FIELD) || getBlock()->isContainedByTOC()));
376 if(bDoGrey && isInSelectedTOC())
377 {
378 bDoGrey = false;
379 }
380 if(!bDoGrey)
381 {
382 m_FillType.Fill(pG,srcX,srcY,x,y,width,height);
383 }
384 else
385 {
386 if(x>=xoff && width <= getWidth())
387 {
388 UT_RGBColor grey(192,192,192);
389 // UT_RGBColor white(255,255,255);
390 GR_Painter painter(pG);
391 // painter.fillRect(white,x,y,width,height);
392 painter.fillRect(grey,x,y,width,height);
393 }
394 else
395 {
396 m_FillType.Fill(pG,srcX,srcY,x,y,width,height);
397 }
398 }
399 }
400
lookupProperties(GR_Graphics * pG)401 void fp_Run::lookupProperties(GR_Graphics * pG)
402 {
403 const PP_AttrProp * pSpanAP = NULL;
404 const PP_AttrProp * pBlockAP = NULL;
405 const PP_AttrProp * pSectionAP = NULL; // TODO do we care about section-level inheritance?
406 bool bGraphicsNull = false;
407 getBlockAP(pBlockAP);
408
409 PD_Document * pDoc = m_pBL->getDocument();
410
411 #ifdef FPRUN_PROPS_MINI_DUMP
412 UT_DEBUGMSG(("fp_Run::lookupProperties: dumping block AP\n"));
413 if(pBlockAP)
414 pBlockAP->miniDump(pDoc);
415 #endif
416 // examining the m_pRevisions contents is too involved, it is
417 // faster to delete it and create a new instance if needed
418 DELETEP(m_pRevisions);
419
420 setVisibility(FP_VISIBLE); // set default visibility
421
422 // NB the call will recreate m_pRevisions for us and it will
423 // change visibility if it is affected by the presence of revisions
424 if(!getBlock()->isContainedByTOC())
425 {
426 getSpanAP(pSpanAP);
427 }
428 else
429 {
430 pSpanAP = pBlockAP;
431 }
432 xxx_UT_DEBUGMSG(("fp_Run: pSpanAP %x \n",pSpanAP));
433
434 #ifdef FPRUN_PROPS_MINI_DUMP
435 UT_DEBUGMSG(("fp_Run::lookupProperties: dumping span AP\n"));
436 if(pSpanAP)
437 pSpanAP->miniDump(pDoc);
438 #endif
439
440 //evaluate the "display" property and superimpose it over anything
441 //we got as the result of revisions
442 const gchar *pszDisplay = PP_evalProperty("display",pSpanAP,pBlockAP,
443 pSectionAP, pDoc, true);
444
445 if(pszDisplay && !strcmp(pszDisplay,"none"))
446 {
447 if(m_eVisibility == FP_VISIBLE)
448 setVisibility(FP_HIDDEN_TEXT);
449 else
450 setVisibility(FP_HIDDEN_REVISION_AND_TEXT);
451 }
452
453 // here we handle background colour -- we parse the property into
454 // m_pColorHL and then call updateHighlightColor() to overlay any
455 // colour from higher layout elements
456 const char * pszBGcolor = PP_evalProperty("bgcolor",pSpanAP,pBlockAP,pSectionAP, pDoc, true);
457 _setColorHL(pszBGcolor);
458 // m_FillType.setColor(pszBGcolor); // we should clear with screen color
459 // and draw with background color
460 if(pG == NULL)
461 {
462 m_bPrinting = false;
463 pG = getGraphics();
464 bGraphicsNull = true;
465 }
466 else if(pG->queryProperties(GR_Graphics::DGP_PAPER))
467 {
468 m_bPrinting = true;
469 }
470 if(!m_pBL->isContainedByTOC())
471 {
472 if(bGraphicsNull)
473 _lookupProperties(pSpanAP, pBlockAP, pSectionAP,NULL);
474 else
475 _lookupProperties(pSpanAP, pBlockAP, pSectionAP,pG);
476 }
477 else
478 {
479 if(bGraphicsNull)
480 _lookupProperties(NULL, pBlockAP, pSectionAP,NULL);
481 else
482 _lookupProperties(NULL, pBlockAP, pSectionAP,pG);
483 }
484 const char * szAuthorInt = NULL;
485 if(pSpanAP && pDoc->isShowAuthors())
486 {
487 if(pSpanAP->getAttribute(PT_AUTHOR_NAME,szAuthorInt))
488 {
489 if(szAuthorInt)
490 m_iAuthorColor = atoi(szAuthorInt);
491 }
492 }
493 else
494 {
495 m_iAuthorColor = 0;
496 }
497 // here we used to set revision-based visibility, but that has to
498 // be done inside getSpanAP() because we need to know whether the
499 // revision is to be visible or not before we can properly apply
500 // any properties the revision contains.
501
502 }
503 #undef FPRUN_PROPS_MINI_DUMP
504 //////////////////////////////////////////////////////////////////
505 //////////////////////////////////////////////////////////////////
506
507 /*
508 Determine best split point in Run
509 \param iMaxLeftWidth Width to split at
510 \retval si Split information (left width, right width, and position)
511 \param bForce Force a split at first opportunity (max width)
512 \return True if split point was found in this Run, otherwise false.
513
514 This implementation simply returns false, forcing line breaker to
515 look for a split point in previous Runs.
516 */
findMaxLeftFitSplitPoint(UT_sint32,fp_RunSplitInfo &,bool)517 bool fp_Run::findMaxLeftFitSplitPoint(UT_sint32 /* iMaxLeftWidth */,
518 fp_RunSplitInfo& /* si */,
519 bool /* bForce */)
520 {
521 return false;
522 }
523
hasLayoutProperties(void) const524 bool fp_Run::hasLayoutProperties(void) const
525 {
526 return false;
527 }
528
529 /*!
530 Find previous Run in block which holds property information
531 \return Run with property information or NULL
532 */
533 fp_Run*
_findPrevPropertyRun(void) const534 fp_Run::_findPrevPropertyRun(void) const
535 {
536 fp_Run* pRun = getPrevRun();
537 while (pRun && (!pRun->hasLayoutProperties() || pRun->isHidden() || (pRun->getType() == FPRUN_IMAGE)))
538 pRun = pRun->getPrevRun();
539 if(pRun == NULL)
540 {
541 pRun = getPrevRun();
542 while (pRun && (!pRun->hasLayoutProperties() || pRun->isHidden()))
543 pRun = pRun->getPrevRun();
544
545 }
546 return pRun;
547 }
548
displayAnnotations(void) const549 bool fp_Run::displayAnnotations(void) const
550 {
551 if(!getBlock())
552 return false;
553 if(!getBlock()->getDocLayout())
554 return false;
555 return getBlock()->getDocLayout()->displayAnnotations();
556 }
557
displayRDFAnchors(void) const558 bool fp_Run::displayRDFAnchors(void) const
559 {
560 if(!getBlock())
561 return false;
562 if(!getBlock()->getDocLayout())
563 return false;
564 return getBlock()->getDocLayout()->displayRDFAnchors();
565 }
566
567 /*!
568 Inherit attribute properties from previous Run
569
570 This is used by Runs for which it does not make sense to have
571 properties, such as forced line breaks end EOP Runs.
572 */
573 void
_inheritProperties(void)574 fp_Run::_inheritProperties(void)
575 {
576 fp_Run* pRun = _findPrevPropertyRun();
577 if (pRun)
578 {
579 xxx_UT_DEBUGMSG(("fp_Run::_inheritProperties: from prev run\n"));
580 _setAscent(pRun->getAscent());
581 _setDescent(pRun->getDescent());
582 _setHeight(pRun->getHeight());
583 xxx_UT_DEBUGMSG(("fp_Run::_inheritProperties: from prev run height is %d \n",getHeight()));
584
585 }
586 else
587 {
588 // look for fonts in this DocLayout's font cache
589 //UT_DEBUGMSG(("fp_Run::_inheritProperties: from current font\n"));
590 const PP_AttrProp * pSpanAP = NULL;
591 const PP_AttrProp * pBlockAP = NULL;
592 const PP_AttrProp * pSectionAP = NULL; // TODO do we care about section-level inheritance?
593
594 //m_pBL->getSpanAttrProp(getBlockOffset(),true,&pSpanAP);
595 getSpanAP(pSpanAP);
596 getBlockAP(pBlockAP);
597
598 FL_DocLayout * pLayout = getBlock()->getDocLayout();
599 const GR_Font * pFont = pLayout->findFont(pSpanAP,pBlockAP,pSectionAP,getGraphics());
600
601 if ((pFont != _getFont()) || (getType() == FPRUN_ENDOFPARAGRAPH))
602 {
603 _setFont(pFont);
604 _setAscent(getGraphics()->getFontAscent(pFont));
605 _setDescent(getGraphics()->getFontDescent(pFont));
606 _setHeight(getGraphics()->getFontHeight(pFont));
607 }
608 xxx_UT_DEBUGMSG(("fp_Run::_inheritProperties: No prev run run height is %d \n",getHeight()));
609 }
610 }
611
getGraphics(void) const612 GR_Graphics * fp_Run::getGraphics(void) const
613 {
614 if(m_bPrinting)
615 {
616 if(getBlock()->getDocLayout()->isQuickPrint())
617 {
618 return getBlock()->getDocLayout()->getQuickPrintGraphics();
619 }
620 }
621 if(getBlock()->getView())
622 {
623 return getBlock()->getView()->getGraphics();
624 }
625 return getBlock()->getDocLayout()->getGraphics();
626 }
627
insertIntoRunListBeforeThis(fp_Run & newRun)628 void fp_Run::insertIntoRunListBeforeThis(fp_Run& newRun)
629 {
630 newRun.unlinkFromRunList();
631 newRun.setNextRun(this);
632 if (m_pPrev)
633 {
634 m_pPrev->setNextRun(&newRun);
635 if(newRun.getType()!= FPRUN_HYPERLINK)
636 newRun.setHyperlink( m_pPrev->getHyperlink());
637 }
638 newRun.setPrevRun(m_pPrev);
639 setPrevRun(&newRun);
640
641 }
642
insertIntoRunListAfterThis(fp_Run & newRun)643 void fp_Run::insertIntoRunListAfterThis(fp_Run& newRun)
644 {
645 newRun.unlinkFromRunList();
646 newRun.setPrevRun(this);
647 if(newRun.getType()!= FPRUN_HYPERLINK)
648 newRun.setHyperlink(m_pHyperlink);
649 if (m_pNext)
650 {
651 m_pNext->setPrevRun(&newRun);
652 }
653 newRun.setNextRun(m_pNext);
654 setNextRun(&newRun);
655 }
656
unlinkFromRunList()657 void fp_Run::unlinkFromRunList()
658 {
659 //first if this is the start of a hyperlink run,
660 //remove the references to it from the following runs
661 if(getType() == FPRUN_HYPERLINK)
662 {
663 fp_HyperlinkRun * pH = static_cast<fp_HyperlinkRun*>(this);
664 if(pH->isStartOfHyperlink())
665 {
666 fp_Run * pRun = getNextRun();
667
668 while(pRun && pRun->getHyperlink() == pH)
669 {
670 pRun->setHyperlink(NULL);
671 pRun = pRun->getNextRun();
672 }
673 }
674 }
675
676 if (m_pPrev)
677 {
678 m_pPrev->setNextRun(m_pNext);
679 }
680 if (m_pNext)
681 {
682 m_pNext->setPrevRun(m_pPrev);
683 setNextRun(0);
684 }
685 setPrevRun(0);
686 }
687
setHyperlink(fp_HyperlinkRun * pH)688 void fp_Run::setHyperlink(fp_HyperlinkRun * pH)
689 {
690 if(pH != m_pHyperlink)
691 {
692 _setHyperlink(pH);
693 clearScreen();
694 }
695 }
696
697 /*! returns PP_AttrProp associated with this span, taking on board the
698 presence of revisions
699 \returns pSpan : location to store the PP_AttrProp
700 */
getSpanAP(void)701 const PP_AttrProp * fp_Run::getSpanAP(void)
702 {
703 const PP_AttrProp * pAP = NULL;
704 getSpanAP(pAP);
705 return pAP;
706 }
707
708 /*! returns PP_AttrProp associated with this span, taking on board the
709 presence of revisions
710 \param pSpan : location to store the PP_AttrProp
711 */
getSpanAP(const PP_AttrProp * & pSpanAP)712 void fp_Run::getSpanAP(const PP_AttrProp * &pSpanAP)
713 {
714 if(getBlock()->isContainedByTOC())
715 {
716 getBlockAP(pSpanAP);
717 return;
718 }
719
720 //first we need to ascertain if this revision is visible
721 FV_View* pView = _getView();
722 UT_return_if_fail(pView);
723
724 UT_uint32 iId = pView->getRevisionLevel();
725 bool bShow = pView->isShowRevisions();
726 bool bHiddenRevision = false;
727
728 if(getType() != FPRUN_FMTMARK && getType() != FPRUN_DUMMY && getType() != FPRUN_DIRECTIONMARKER)
729 {
730 getBlock()->getSpanAttrProp(getBlockOffset(),false,&pSpanAP,&m_pRevisions,bShow,iId,bHiddenRevision);
731 }
732 else
733 {
734 getBlock()->getSpanAttrProp(getBlockOffset(),true,&pSpanAP,&m_pRevisions,bShow,iId,bHiddenRevision);
735 }
736 if(pSpanAP == NULL)
737 {
738 // FIXME for now lets work around this
739 // UT_ASSERT(UT_SHOULD_NOT_HAPPEN); track these down later.
740 //
741 getBlockAP(pSpanAP);
742 return;
743 }
744 if(bHiddenRevision)
745 {
746 setVisibility(FP_HIDDEN_REVISION);
747 }
748 else
749 {
750 setVisibility(FP_VISIBLE);
751 }
752 }
753
setX(UT_sint32 iX,bool)754 void fp_Run::setX(UT_sint32 iX, bool /*bDontClearIfNeeded*/)
755 {
756 Run_setX(iX, FP_CLEARSCREEN_AUTO);
757 }
758
759 // the parameter eClearScreen has a default value AUTO
760 // we need this extra parameter be able to specify false when calling from
761 // inside of the first pass of fp_Line::layout(), which sets
762 // only a temporary value of iX which is then adjusted in the
763 // second pass, without this the run will redraw twice, once always unnecessarily
764 // and most of the time both times unnecessarily
Run_setX(UT_sint32 iX,FPRUN_CLEAR_SCREEN eClearScreen)765 void fp_Run::Run_setX(UT_sint32 iX, FPRUN_CLEAR_SCREEN eClearScreen)
766 {
767 switch(eClearScreen)
768 {
769 case FP_CLEARSCREEN_AUTO:
770 if (iX == m_iX)
771 {
772 return;
773 }
774 //otherwise fall through
775 case FP_CLEARSCREEN_FORCE:
776 m_iX = m_iOldX;
777 clearScreen();
778 m_iOldX = iX;
779 m_iX = iX;
780 break;
781 case FP_CLEARSCREEN_NEVER:
782 // only set m_iX and leave m_iOldX alone; this allows for
783 // multiple calls to setX with the NEVER parameter without
784 // intervening FORCE or AUTO
785 m_iX = iX;
786 break;
787 default:
788 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
789 }
790
791 }
792
setY(UT_sint32 iY)793 void fp_Run::setY(UT_sint32 iY)
794 {
795 if (iY == m_iY)
796 {
797 return;
798 }
799
800 clearScreen();
801
802 m_iY = iY;
803 }
804
setLine(fp_Line * pLine)805 void fp_Run::setLine(fp_Line* pLine)
806 {
807 if (pLine == m_pLine)
808 {
809 return;
810 }
811 if(!getBlock()->getDocSectionLayout()->isCollapsing())
812 clearScreen();
813
814 m_pLine = pLine;
815 if(pLine != NULL)
816 {
817 m_FillType.setParent(&pLine->getFillType());
818 }
819 else
820 {
821 m_FillType.setParent(NULL);
822 }
823 }
824
825
826 /*
827 In the BIDI build, changing runs next or previous can result in
828 change of visual appearance of the run or a run immediately adjucent
829 (say deleting last character of a word may require that the new
830 last character is displayed using a final-form glyph which).
831 Consequently we need to mark the width and draw buffer as dirty,
832 and that is what happens when the bRefresh is true (which is the
833 default value). However, the refresh is very expensive, and sometimes
834 we know that it is not needed (e.g. simply merging neigbouring runs
835 does not change context, merely the way we store the stuff) -- in that
836 case we specify bRefresh false
837
838 */
839
setNextRun(fp_Run * p,bool bRefresh)840 void fp_Run::setNextRun(fp_Run* p, bool bRefresh)
841 {
842 if(p != m_pNext)
843 {
844 // change of context, need to refresh draw buffer if context sensitive
845 if(bRefresh)
846 orDrawBufferDirty(GRSR_ContextSensitive);
847
848 //m_bRecalcWidth |= bRefresh; -- will be taken care of when
849 //buffer is recalculated
850 #if 0
851 // we do not do ligatures across run boundaries any more,
852 // Tomas, Nov 15, 2003
853 // because we support 2-char ligatures, the change of next
854 // can also influence the run ahead of us
855 // we will just mark it
856 if(m_pPrev && bRefresh)
857 {
858 m_pPrev->markDrawBufferDirty();
859 m_pPrev->markWidthDirty();
860 }
861 #endif
862 m_pNext = p;
863 }
864 }
865
setPrevRun(fp_Run * p,bool bRefresh)866 void fp_Run::setPrevRun(fp_Run* p, bool bRefresh)
867 {
868 if(p != m_pPrev)
869 {
870 // change of context, need to refresh draw buffer if context sensitive
871 if(bRefresh)
872 orDrawBufferDirty(GRSR_ContextSensitive);
873
874 // m_bRecalcWidth |= bRefresh; -- will be taken care of when
875 // buffer is recacluated
876 #if 0
877 // we do not do ligatures across run boundaries any more,
878 // Tomas, Nov 15, 2003
879 // because we support 2-char ligatures, the change of prev
880 // can also influence the run that follows us
881 // we will just mark it
882 if(m_pNext && bRefresh)
883 {
884 m_pNext->markDrawBufferDirty();
885 m_pNext->markWidthDirty();
886 }
887 #endif
888 m_pPrev = p;
889 }
890 }
891
isLastRunOnLine(void) const892 bool fp_Run::isLastRunOnLine(void) const
893 {
894 return (getLine()->getLastRun() == this);
895 }
896
isFirstRunOnLine(void) const897 bool fp_Run::isFirstRunOnLine(void) const
898 {
899 return (getLine()->getFirstRun() == this);
900 }
901
isLastVisRunOnLine(void) const902 bool fp_Run::isLastVisRunOnLine(void) const
903 {
904 return (getLine()->getLastVisRun() == this);
905 }
906
isFirstVisRunOnLine(void) const907 bool fp_Run::isFirstVisRunOnLine(void) const
908 {
909 return (getLine()->getFirstVisRun() == this);
910 }
911
markAsDirty(void)912 void fp_Run::markAsDirty(void)
913 {
914 xxx_UT_DEBUGMSG(("Run %x marked dirty \n"));
915 m_bDirty = true;
916 }
917
918
919 /*!
920 * return an rectangle that covers this object on the screen
921 * The calling routine is resposible for deleting the returned struct
922 */
getScreenRect(void)923 UT_Rect * fp_Run::getScreenRect(void)
924 {
925 UT_sint32 xoff = 0;
926 UT_sint32 yoff = 0;
927 UT_Rect * pRec = NULL;
928 fp_Line * pLine = getLine();
929 if(pLine)
930 {
931 pLine->getScreenOffsets(this,xoff,yoff);
932 pRec= new UT_Rect(xoff,yoff,getWidth(),getHeight());
933 return pRec;
934 }
935 else
936 {
937 return NULL;
938 }
939 }
940
941 /*!
942 * Marks Dirty any runs that overlap the supplied rectangle. This rectangle
943 * is relative to the screen.
944 */
markDirtyOverlappingRuns(UT_Rect & recScreen)945 void fp_Run::markDirtyOverlappingRuns(UT_Rect & recScreen)
946 {
947 UT_Rect * pRec = NULL;
948 pRec = getScreenRect();
949 if(pRec && recScreen.intersectsRect(pRec))
950 {
951 fp_Run::markAsDirty();
952 delete pRec;
953 return;
954 }
955 DELETEP(pRec);
956 return;
957 }
958
setCleared(void)959 void fp_Run::setCleared(void)
960 {
961 m_bIsCleared = true;
962 }
963
isOnlyRunOnLine(void) const964 bool fp_Run::isOnlyRunOnLine(void) const
965 {
966 if (getLine()->countRuns() == 1)
967 {
968 UT_ASSERT(isFirstRunOnLine());
969 UT_ASSERT(isLastRunOnLine());
970
971 return true;
972 }
973
974 return false;
975 }
976
setLength(UT_uint32 iLen,bool bRefresh)977 void fp_Run::setLength(UT_uint32 iLen, bool bRefresh)
978 {
979 if (iLen == getLength())
980 {
981 return;
982 }
983 m_bRecalcWidth |= bRefresh;
984 if(getWidth() > 0)
985 clearScreen();
986 // UT_ASSERT((getType() == FPRUN_FMTMARK) || (iLen > 0));
987 m_iLen = iLen;
988
989 // change of length generally means something got deleted, and
990 // that affects all text in the present run, and shaping in the
991 // runs adjacent
992 if(bRefresh)
993 {
994 orDrawBufferDirty(GRSR_Unknown);
995
996 if(m_pPrev)
997 {
998 m_pPrev->orDrawBufferDirty(GRSR_ContextSensitive);
999 }
1000
1001 if(m_pNext)
1002 {
1003 m_pNext->orDrawBufferDirty(GRSR_ContextSensitive);
1004 }
1005 }
1006 }
1007
clearPrint(void)1008 void fp_Run::clearPrint(void)
1009 {
1010 m_bPrinting =false;
1011 }
1012
setBlockOffset(UT_uint32 offset)1013 void fp_Run::setBlockOffset(UT_uint32 offset)
1014 {
1015 UT_DebugOnly<UT_sint32> iOff = static_cast<UT_sint32>(offset);
1016 UT_ASSERT(iOff >=0);
1017 m_iOffsetFirst = offset;
1018 }
1019
clearScreen(void)1020 void fp_Run::clearScreen(void)
1021 {
1022 Run_ClearScreen(false);
1023 }
1024
Run_ClearScreen(bool bFullLineHeightRect)1025 void fp_Run::Run_ClearScreen(bool bFullLineHeightRect)
1026 {
1027 if(m_bPrinting)
1028 {
1029 return;
1030 }
1031 if(!getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN))
1032 {
1033 return;
1034 }
1035 markAsDirty();
1036 if (m_bIsCleared && !getMustClearScreen())
1037 {
1038 // no need to clear if we've already done so.
1039 return;
1040 }
1041 m_bMustClearScreen = false;
1042
1043 if (!getLine())
1044 {
1045 // nothing to clear if this run is not currently on a line
1046 return;
1047 }
1048 xxx_UT_DEBUGMSG(("SEVIOR: Doing Run_ClearScreen in run %x \n",this));
1049 getLine()->getFillType().setIgnoreLineLevel(true);
1050 if(getLine()->getContainer() != NULL)
1051 {
1052 if(getLine()->getContainer()->getPage() != 0)
1053 {
1054 UT_Rect clip(0,0,0,0);
1055 if(isSelectionDraw())
1056 {
1057 if(getType() == FPRUN_TEXT)
1058 {
1059 bool bRTL = (getVisDirection() == UT_BIDI_RTL);
1060
1061 UT_sint32 xoff,yoff;
1062 getLine()->getScreenOffsets(this, xoff, yoff);
1063 UT_sint32 xLeft = xoff;
1064 UT_sint32 xRight = xLeft + getWidth();
1065 UT_sint32 x1,y1,x2,y2,height;
1066 bool bDir;
1067 if(posSelLow() > getBlock()->getPosition(true) + getBlockOffset())
1068 {
1069 findPointCoords(posSelLow() - getBlock()->getPosition(true), x1,y1,x2,y2,height,bDir);
1070
1071 if(bRTL) //rtl needs translation
1072 {
1073 xRight = x1 + _getView()->getPageViewLeftMargin();
1074 xRight -= _getView()->getXScrollOffset();
1075 }
1076 else
1077 {
1078 xLeft = x1 + _getView()->getPageViewLeftMargin();
1079 xLeft -= _getView()->getXScrollOffset();
1080 }
1081
1082 }
1083 if(posSelHigh() < getBlock()->getPosition(true) + getBlockOffset() + getLength())
1084 {
1085 findPointCoords(posSelHigh() - getBlock()->getPosition(true) +1, x1,y1,x2,y2,height,bDir);
1086 if(bRTL) //rtl needs translation
1087 {
1088 xLeft = x1 + _getView()->getPageViewLeftMargin();
1089 xLeft -= _getView()->getXScrollOffset();
1090 }
1091 else
1092 {
1093 xRight = x1 + _getView()->getPageViewLeftMargin();
1094 xRight -= _getView()->getXScrollOffset();
1095 }
1096 }
1097 clip.set(xLeft,yoff,xRight-xLeft,getLine()->getHeight());
1098 getGraphics()->setClipRect(&clip);
1099 }
1100 }
1101 _clearScreen(bFullLineHeightRect);
1102 if(isSelectionDraw())
1103 {
1104 getGraphics()->setClipRect(NULL);
1105 }
1106 // make sure we only get erased once
1107 _setDirty(true);
1108 m_bIsCleared = true;
1109 }
1110 else
1111 {
1112 xxx_UT_DEBUGMSG(("fp_Run: Clearscreen on line without page \n"));
1113 }
1114 }
1115 else
1116 {
1117 xxx_UT_DEBUGMSG(("fpRun: Clearscreen on line without container \n"));
1118 }
1119 fp_Line * pLine = getLine();
1120 if(pLine)
1121 {
1122 pLine->setNeedsRedraw();
1123 pLine->getFillType().setIgnoreLineLevel(false);
1124 }
1125
1126 xxx_UT_DEBUGMSG(("fp_Run: clearscreen applied \n"));
1127 }
1128
1129 static UT_RGBColor s_fgColor;
1130
getFGColor(void) const1131 const UT_RGBColor fp_Run::getFGColor(void) const
1132 {
1133 // revision colours
1134 FV_View * pView = _getView();
1135 UT_return_val_if_fail(pView, s_fgColor);
1136 bool bShow = pView->isShowRevisions();
1137 if(getBlock()->getDocLayout()->displayAnnotations())
1138 {
1139 if(getLine() && getLine()->getContainer() && getLine()->getContainer()->getContainerType() == FP_CONTAINER_ANNOTATION)
1140 {
1141 fp_AnnotationContainer * pAC = static_cast<fp_AnnotationContainer *>(getLine()->getContainer());
1142 UT_uint32 pid = pAC->getPID();
1143 s_fgColor = _getView()->getColorAnnotation(pAC->getPage(),pid);
1144 return s_fgColor;
1145 }
1146 }
1147 if(m_pRevisions && bShow)
1148 {
1149 bool bMark = pView->isMarkRevisions();
1150 UT_uint32 iId = 0;
1151 const PP_Revision * r = NULL;
1152 r = m_pRevisions->getLastRevision();
1153
1154 UT_return_val_if_fail(r != NULL, _getColorFG());
1155
1156 bool bRevColor = false;
1157
1158 if(!bMark)
1159 {
1160 // this is the case when we are in non-marking mode ...
1161 bRevColor = true;
1162 }
1163
1164
1165 UT_uint32 iShowId = pView->getRevisionLevel();
1166
1167 xxx_UT_DEBUGMSG(("fp_Run Revision ID %d ShowRevision ID %d \n",iId,iShowId));
1168 if(bMark && iShowId == 0)
1169 {
1170 // this is the case where we are in marking mode and are
1171 // supposed to reveal all
1172 bRevColor = true;
1173 }
1174
1175 if(bMark && iShowId != 0 && (iId-1 == iShowId))
1176 {
1177 // this is the case when we are in marking mode, and are
1178 // supposed to reveal id > iShowId
1179 bRevColor = true;
1180 }
1181
1182 if(!bRevColor)
1183 return _getColorFG();
1184
1185 s_fgColor = _getView()->getColorRevisions(iId-1);
1186 }
1187 else if(m_pHyperlink && getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN) &&
1188 (m_pHyperlink->getHyperlinkType() == HYPERLINK_NORMAL))
1189 {
1190 s_fgColor = _getView()->getColorHyperLink();
1191 }
1192 else if(m_pHyperlink && (m_pHyperlink->getHyperlinkType() == HYPERLINK_ANNOTATION))
1193 {
1194 if(getBlock()->getDocLayout()->displayAnnotations())
1195 {
1196 s_fgColor = _getView()->getColorAnnotation(this);
1197 }
1198 else
1199 return _getColorFG();
1200 }
1201 else if(m_pHyperlink && (m_pHyperlink->getHyperlinkType() == HYPERLINK_RDFANCHOR))
1202 {
1203 if( getBlock()->getDocLayout()->displayRDFAnchors())
1204 {
1205 s_fgColor = _getView()->getColorRDFAnchor(this);
1206 }
1207 else
1208 return _getColorFG();
1209 }
1210 //
1211 // FIXME make priniting author colours a preference.
1212 //
1213 else if((m_iAuthorColor > 0) && !m_bPrinting)
1214 {
1215 UT_sint32 iRange = m_iAuthorColor % 12;
1216 //
1217 // FIXME We can also set this from the color property of the author ID
1218 //
1219 s_fgColor = _getView()->getColorRevisions(iRange);
1220 return s_fgColor;
1221 }
1222 else
1223 return _getColorFG();
1224
1225 return s_fgColor;
1226 }
1227
_setFont(const GR_Font * f)1228 void fp_Run::_setFont(const GR_Font * f)
1229 {
1230 m_pFont = f;
1231
1232 #ifdef DEBUG
1233 if(f)
1234 m_iFontAllocNo = f->getAllocNumber();
1235 #endif
1236 }
1237
_getFont(void) const1238 const GR_Font * fp_Run::_getFont(void) const
1239 {
1240 #ifdef DEBUG
1241 if(m_pFont)
1242 {
1243 // if this assert fails we are in deep trouble; basically, the font pointer points
1244 // to some other font that it was when it was set
1245 UT_ASSERT_HARMLESS( m_iFontAllocNo == m_pFont->getAllocNumber());
1246 }
1247 #endif
1248
1249 return m_pFont;
1250 }
1251
_setDirty(bool b)1252 void fp_Run::_setDirty(bool b)
1253 {
1254 xxx_UT_DEBUGMSG(("fp_Run:: run %x Dirty state set to %d \n",this,b));
1255 m_bDirty = b;
1256 }
1257
draw(dg_DrawArgs * pDA)1258 void fp_Run::draw(dg_DrawArgs* pDA)
1259 {
1260 if (pDA->bDirtyRunsOnly && !m_bDirty)
1261 {
1262 if(!getLine())
1263 return;
1264 if(!getLine()->getPage())
1265 return;
1266 if(!getLine()->getPage()->intersectsDamagedRect(this))
1267 {
1268 xxx_UT_DEBUGMSG(("fp_Run::Run %x not dirty returning \n",this));
1269 return;
1270 }
1271 m_bDirty = true;
1272 }
1273 const UT_Rect * pPrevClip = pDA->pG->getClipRect();
1274 if(isHidden())
1275 {
1276 // this run is marked as hidden, nothing to do
1277 return;
1278 }
1279 m_bIsCleared = false;
1280 fp_Line * pLine = getLine();
1281 if (pLine)
1282 pLine->setScreenCleared(false);
1283
1284 //UT_usleep(100000); // 0.1 seconds useful for debugging
1285 xxx_UT_DEBUGMSG(("SEVIOR: draw Run this %x line %x \n",this, getLine()));
1286 GR_Graphics * pG = pDA->pG;
1287 // shortcircuit drawing if we're way off base.
1288 long imax = (1 << 30) - 1; // This draws four rows of pages. Increase the 30 to view more rows.
1289 if (((pDA->yoff < -imax) || (pDA->yoff > imax)) && pG->queryProperties(GR_Graphics::DGP_SCREEN))
1290 return;
1291
1292 if(pG->queryProperties(GR_Graphics::DGP_PAPER))
1293 {
1294 m_bPrinting = true;
1295 lookupProperties(pG);
1296 }
1297 pG->setColor(getFGColor());
1298 UT_Rect clip(0,0,0,0);
1299 bool bSetClip = false;
1300 if(isSelectionDraw())
1301 {
1302 if((getType() == FPRUN_TEXT) && getLine())
1303 {
1304 bool bRTL = (getVisDirection() == UT_BIDI_RTL);
1305 UT_sint32 xLeft = pDA->xoff;
1306 UT_sint32 xRight = xLeft + getWidth();
1307 UT_sint32 x1,y1,x2,y2,height;
1308 bool bDir;
1309 FL_DocLayout * pLayout = getBlock()->getDocLayout();
1310 UT_uint32 iPageNumber = pLayout->findPage(pLine->getPage());
1311 UT_uint32 widthPrevPageInRow = _getView()->getWidthPrevPagesInRow(iPageNumber);
1312 if(posSelLow() > getBlock()->getPosition(true) + getBlockOffset())
1313 {
1314 findPointCoords(posSelLow() - getBlock()->getPosition(true), x1,y1,x2,y2,height,bDir);
1315 x1 += widthPrevPageInRow;
1316 x2 += widthPrevPageInRow;
1317 if(bRTL)
1318 {
1319 xRight = x1 + _getView()->getPageViewLeftMargin();
1320 xRight -= _getView()->getXScrollOffset();
1321 }
1322 else
1323 {
1324 xLeft = x1 + _getView()->getPageViewLeftMargin();
1325 xLeft -= _getView()->getXScrollOffset();
1326 }
1327 }
1328 if(posSelHigh() < getBlock()->getPosition(true) + getBlockOffset() + getLength())
1329 {
1330 findPointCoords(posSelHigh() - getBlock()->getPosition(true) +1, x1,y1,x2,y2,height,bDir);
1331 x1 += widthPrevPageInRow;
1332 x2 += widthPrevPageInRow;
1333 if(bRTL)
1334 {
1335 xLeft = x1 + _getView()->getPageViewLeftMargin();
1336 xLeft -= _getView()->getXScrollOffset();
1337 }
1338 else
1339 {
1340 xRight = x1 + _getView()->getPageViewLeftMargin();
1341 xRight -= _getView()->getXScrollOffset();
1342 }
1343 }
1344 UT_sint32 width = xRight-xLeft;
1345 clip.set(xLeft,pDA->yoff-getLine()->getAscent(),width,getLine()->getHeight());
1346 bSetClip = true;
1347 pDA->pG->setClipRect(&clip);
1348 xxx_UT_DEBUGMSG(("draw cliprect left %d width %d \n",clip.left,clip.width));
1349 }
1350 }
1351 UT_RGBColor OldCol = *m_FillType.getColor();
1352 UT_RGBColor bgCol = _getColorHL();
1353 xxx_UT_DEBUGMSG((" bg red %d rg blue %d bg green %d trans %d \n",bgCol.m_red,bgCol.m_blu,bgCol.m_grn,bgCol.m_bIsTransparent));
1354 if(!bgCol.isTransparent())
1355 {
1356 m_FillType.setColor(bgCol);
1357 }
1358 xxx_UT_DEBUGMSG(("Drawing pDA->yoff %d \n",pDA->yoff));
1359 _draw(pDA);
1360 if(!bgCol.isTransparent())
1361 {
1362 m_FillType.setColor(OldCol); // restore the old clear color
1363 }
1364 if(bSetClip)
1365 {
1366 pDA->pG->setClipRect(pPrevClip);
1367 }
1368 FV_View* pView = _getView();
1369 UT_return_if_fail(pView);
1370 bool bShowRevs = pView->isShowRevisions();
1371
1372 UT_uint32 i2Du = pDA->pG->tlu(1); // changed this to 1 to fix various pixel dirt
1373
1374 if(m_pRevisions && bShowRevs)
1375 {
1376 GR_Painter painter(pG);
1377 const PP_Revision * r = m_pRevisions->getLastRevision();
1378 UT_ASSERT(r != NULL);
1379
1380 if (r) {
1381 PP_RevisionType r_type = r->getType();
1382 UT_uint32 iId = r->getId();
1383 UT_uint32 iShowId = pView->getRevisionLevel();
1384 bool bMark = pView->isMarkRevisions();
1385
1386 if(bMark && iShowId != 0)
1387 iId--;
1388
1389 if(!bMark || !iShowId || iId == iShowId)
1390 {
1391 pG->setColor(getFGColor());
1392
1393 UT_uint32 iWidth = getDrawingWidth();
1394
1395 if(r_type == PP_REVISION_ADDITION || r_type == PP_REVISION_ADDITION_AND_FMT)
1396 {
1397 painter.fillRect(s_fgColor,pDA->xoff, pDA->yoff + i2Du, iWidth, getGraphics()->tlu(1));
1398 painter.fillRect(s_fgColor,pDA->xoff, pDA->yoff + i2Du + getGraphics()->tlu(2),
1399 iWidth, getGraphics()->tlu(1));
1400
1401 }
1402 else if(r_type == PP_REVISION_FMT_CHANGE)
1403 {
1404 // draw a thick line underneath
1405 painter.fillRect(s_fgColor,pDA->xoff, pDA->yoff + i2Du, iWidth, getGraphics()->tlu(2));
1406 }
1407 else
1408 {
1409 // draw a strike-through line
1410
1411 painter.fillRect(s_fgColor,pDA->xoff, pDA->yoff - m_iHeight/3,
1412 iWidth, getGraphics()->tlu(2));
1413 }
1414 }
1415 }
1416 }
1417
1418 if(m_pHyperlink && pG->queryProperties(GR_Graphics::DGP_SCREEN))
1419 {
1420 // have to set the colour again, since fp_TextRun::_draw can set it to red
1421 // for drawing sguiggles
1422 if(m_pHyperlink->getHyperlinkType() == HYPERLINK_NORMAL)
1423 {
1424 GR_Painter painter(pG);
1425 pG->setColor(_getView()->getColorHyperLink());
1426 pG->setLineProperties(pG->tluD(1.0),
1427 GR_Graphics::JOIN_MITER,
1428 GR_Graphics::CAP_PROJECTING,
1429 GR_Graphics::LINE_SOLID);
1430
1431 painter.drawLine(pDA->xoff, pDA->yoff + i2Du, pDA->xoff + m_iWidth, pDA->yoff + i2Du);
1432 }
1433 else
1434 {
1435 bool display = false;
1436 GR_Painter painter(pG);
1437 switch(m_pHyperlink->getHyperlinkType())
1438 {
1439 case HYPERLINK_NORMAL:
1440 break;
1441 case HYPERLINK_RDFANCHOR:
1442 if( displayRDFAnchors() )
1443 {
1444 display = true;
1445 pG->setColor(_getView()->getColorRDFAnchor(this));
1446 }
1447 break;
1448 case HYPERLINK_ANNOTATION:
1449 if(displayAnnotations() || pG->queryProperties(GR_Graphics::DGP_SCREEN))
1450 {
1451 display = true;
1452 pG->setColor(_getView()->getColorAnnotation(this));
1453 }
1454 break;
1455 }
1456
1457 if( display )
1458 {
1459 pG->setLineProperties(pG->tluD(1.0),
1460 GR_Graphics::JOIN_MITER,
1461 GR_Graphics::CAP_PROJECTING,
1462 GR_Graphics::LINE_ON_OFF_DASH);
1463
1464 painter.drawLine(pDA->xoff, pDA->yoff + i2Du, pDA->xoff + m_iWidth, pDA->yoff + i2Du);
1465 pG->setLineProperties(pG->tluD(1.0),
1466 GR_Graphics::JOIN_MITER,
1467 GR_Graphics::CAP_PROJECTING,
1468 GR_Graphics::LINE_SOLID);
1469 }
1470 }
1471 }
1472
1473 if(m_eVisibility == FP_HIDDEN_TEXT || m_eVisibility == FP_HIDDEN_REVISION_AND_TEXT)
1474 {
1475 GR_Painter painter(pG);
1476 pG->setColor(getFGColor());
1477 pG->setLineProperties(pG->tluD(1.0),
1478 GR_Graphics::JOIN_MITER,
1479 GR_Graphics::CAP_PROJECTING,
1480 GR_Graphics::LINE_DOTTED);
1481
1482 painter.drawLine(pDA->xoff, pDA->yoff + i2Du, pDA->xoff + m_iWidth, pDA->yoff + i2Du);
1483
1484 }
1485 m_bIsCleared = false;
1486 _setDirty(false);
1487 if(pG->queryProperties(GR_Graphics::DGP_PAPER))
1488 {
1489 m_bPrinting = false;
1490 //
1491 // The font will be reset by refreshRunProperties()
1492 // After the print has finished.
1493 //
1494 _setFont(NULL);
1495 lookupProperties(NULL);
1496 }
1497 }
1498
1499 /*!
1500 Determines if run is currently visible or hidden
1501 run is hidden in the following circumstances:
1502
1503 a) it is formatted as hidden and show para is off
1504
1505 b) it is part of a revision that makes it hidden; several cases
1506 fall into this category, but that is immaterial here (the
1507 decision on this is made in lookupProperties()
1508 bool fp_Run::isHidden() const
1509 */
1510
1511 /*!
1512 Determines if run would be hidden if its visibility was set to the
1513 given value eVisibility
1514 */
_wouldBeHidden(FPVisibility eVisibility) const1515 bool fp_Run::_wouldBeHidden(FPVisibility eVisibility) const
1516 {
1517 FV_View* pView = _getView();
1518 bool bShowHidden = pView->getShowPara();
1519
1520 bool bHidden = ((eVisibility == FP_HIDDEN_TEXT && !bShowHidden)
1521 || eVisibility == FP_HIDDEN_REVISION
1522 || eVisibility == FP_HIDDEN_REVISION_AND_TEXT);
1523
1524 return bHidden;
1525 }
1526
1527 /*!
1528 changes the visibility of the present run; this requires
1529 invalidating different things depending on circumstances
1530 */
setVisibility(FPVisibility eVis)1531 void fp_Run::setVisibility(FPVisibility eVis)
1532 {
1533 if(m_eVisibility == eVis)
1534 return;
1535
1536 if(eVis == FP_HIDDEN_TEXT && !_wouldBeHidden(eVis) && m_iWidth == 0)
1537 {
1538 // we are asked to mark text as hidden, and under the present settings it would be
1539 // visible, but its width == 0. While the 0 width could be legitimate, it is more
1540 // likely that the run was previously hidden due to ShowPara == false and now is
1541 // being shown -- we need to make sure everything gets updated
1542 // (this case avoids the logic below, because of the way that lookupProperties()
1543 // works -- it might be worth redesigning that
1544 m_bIsCleared = true;
1545 m_bDirty = true;
1546 m_bRecalcWidth = true;
1547 m_eVisibility = eVis;
1548 return;
1549 }
1550
1551 if( (isHidden() && _wouldBeHidden(eVis))
1552 || (!isHidden() && !_wouldBeHidden(eVis)))
1553 {
1554 // this run will remain as it is, so we just set visibility to
1555 // the new value
1556 m_eVisibility = eVis;
1557 return;
1558 }
1559
1560 if(_wouldBeHidden(eVis))
1561 {
1562 // we are going into hiding, so we need to clear screen first
1563 clearScreen();
1564
1565 // we do not need to redraw
1566 m_bDirty = false;
1567 m_bRecalcWidth = true;
1568 m_eVisibility = eVis;
1569 return;
1570 }
1571
1572 // we are unhiding: need to mark everything dirty
1573 m_bIsCleared = true;
1574 m_bDirty = true;
1575 m_bRecalcWidth = true;
1576 m_eVisibility = eVis;
1577
1578 /* recalculate width immediately so that any calls to getWidth() are
1579 * accurate
1580 */
1581 _recalcWidth();
1582
1583 return;
1584 }
1585
deleteFollowingIfAtInsPoint() const1586 bool fp_Run::deleteFollowingIfAtInsPoint() const
1587 {
1588 if(isHidden())
1589 return true;
1590 else
1591 return _deleteFollowingIfAtInsPoint();
1592 }
1593
_deleteFollowingIfAtInsPoint() const1594 bool fp_Run::_deleteFollowingIfAtInsPoint() const
1595 {
1596 return false;
1597 }
1598
1599
canContainPoint(void) const1600 bool fp_Run::canContainPoint(void) const
1601 {
1602 if(isHidden())
1603 return false;
1604 else
1605 return _canContainPoint();
1606 }
1607
_canContainPoint(void) const1608 bool fp_Run::_canContainPoint(void) const
1609 {
1610 return true;
1611 }
1612
letPointPass(void) const1613 bool fp_Run::letPointPass(void) const
1614 {
1615 if(isHidden())
1616 return true;
1617 else
1618 return _letPointPass();
1619 }
1620
_letPointPass(void) const1621 bool fp_Run::_letPointPass(void) const
1622 {
1623 return true;
1624 }
1625
recalcWidth(void)1626 bool fp_Run::recalcWidth(void)
1627 {
1628 if(isHidden())
1629 {
1630 if(m_iWidth != 0)
1631 {
1632 m_iWidth = 0;
1633 return true;
1634 }
1635
1636 return false;
1637 }
1638 else
1639 return _recalcWidth();
1640 }
1641
1642 /*!
1643 update ascent, decent and height
1644 */
updateVerticalMetric()1645 void fp_Run::updateVerticalMetric()
1646 {
1647 if(m_pFont)
1648 {
1649 _setAscent(getGraphics()->getFontAscent(m_pFont));
1650 _setDescent(getGraphics()->getFontDescent(m_pFont));
1651 _setHeight(getGraphics()->getFontHeight(m_pFont));
1652 }
1653 }
1654
1655
_recalcWidth(void)1656 bool fp_Run::_recalcWidth(void)
1657 {
1658 // do nothing. subclasses may override this.
1659 return false;
1660 }
1661
drawDecors(UT_sint32 xoff,UT_sint32 yoff,GR_Graphics * pG)1662 void fp_Run::drawDecors(UT_sint32 xoff, UT_sint32 yoff, GR_Graphics * pG)
1663 {
1664 xxx_UT_DEBUGMSG(("drawDecors xoff %d \n",xoff));
1665 /*
1666 Upon entry to this function, yoff is the TOP of the run,
1667 NOT the baseline.
1668 */
1669
1670 /*
1671 Here is the code to work out the position and thickness of under
1672 and overlines for a run of text. This is neccessary because an
1673 underline or overline could shift position depending on the
1674 text size - particularly for subscripts and superscripts. We
1675 can't work out where to put the lines until the end of the
1676 lined span. This info is saved in the fp_Run class. If a
1677 underline or overline is pending (because the next run
1678 continues the underline or overline), mark the next run as
1679 dirty to make sure it is drawn.
1680 */
1681
1682 if((_getDecorations() & (TEXT_DECOR_UNDERLINE | TEXT_DECOR_OVERLINE |
1683 TEXT_DECOR_LINETHROUGH | TEXT_DECOR_TOPLINE | TEXT_DECOR_BOTTOMLINE)) == 0)
1684 {
1685 return;
1686 }
1687
1688 GR_Painter painter(pG);
1689 const UT_sint32 old_LineWidth = m_iLineWidth;
1690 UT_sint32 cur_linewidth = pG->tlu(1) + UT_MAX(pG->tlu(10),static_cast<UT_sint32>(getAscent())-pG->tlu(10))/8;
1691 //
1692 // Line thickness is too thick.
1693 //
1694 cur_linewidth = UT_MAX(pG->tlu(1),cur_linewidth/2);
1695 UT_sint32 iDrop = 0;
1696
1697 // need to do this in the visual space
1698 fp_Run* P_Run = getPrevVisual();
1699 fp_Run* N_Run = getNextVisual();
1700
1701 const bool b_Underline = isUnderline();
1702 const bool b_Overline = isOverline();
1703 const bool b_Strikethrough = isStrikethrough();
1704 const bool b_Topline = isTopline();
1705 const bool b_Bottomline = isBottomline();
1706
1707 // again, need to do this in visual space
1708 const bool b_Firstrun = (P_Run == NULL) || (getLine()->getFirstVisRun()== this);
1709 const bool b_Lastrun = (N_Run == NULL) || (getLine()->getLastVisRun()== this);
1710
1711 /* If the previous run is NULL or if this is the first run of a
1712 line, we are on the first run of the line so set the linethickness,
1713 start of the line span and the overline and underline positions from
1714 the current measurements.
1715 */
1716 if(P_Run == NULL || b_Firstrun )
1717 {
1718 setLinethickness(cur_linewidth);
1719 if(b_Underline)
1720 {
1721 iDrop = yoff + getAscent() + getDescent()/3 + pG->tlu(1);
1722 xxx_UT_DEBUGMSG(("underline getAscent() %d getDescent() %d tlu 1 %d \n",getAscent(),getDescent(), pG->tlu(1)));
1723 setUnderlineXoff( xoff);
1724 setMaxUnderline(iDrop);
1725 }
1726 if(b_Overline)
1727 {
1728 iDrop = yoff + pG->tlu(1) + UT_MAX(pG->tlu(10),static_cast<UT_sint32>(getAscent()) - pG->tlu(10))/8;
1729 setOverlineXoff( xoff);
1730 setMinOverline(iDrop);
1731 }
1732 }
1733 /*
1734 Otherwise look to see if the previous run had an underline or
1735 overline. If it does, merge the information with the present information. Take
1736 the Maximum of the underline offsets and the minimum of the overline offsets.
1737 Always take the maximum of the linewidths. If there is no previous underline
1738 or overline set the underline and overline locations with the current data.
1739 */
1740 else
1741 {
1742 if (!P_Run->isUnderline() && !P_Run->isOverline() &&
1743 !P_Run->isStrikethrough())
1744 {
1745 setLinethickness(cur_linewidth);
1746 }
1747 else
1748 {
1749 setLinethickness(UT_MAX(P_Run->getLinethickness(),cur_linewidth));
1750 }
1751 if (b_Underline)
1752 {
1753 iDrop = yoff + getAscent() + getDescent()/3;
1754 xxx_UT_DEBUGMSG(("underline getAscent() %d getDescent() %d m_iDescent %d \n",getAscent(),getDescent(),m_iDescent));
1755 if(!P_Run->isUnderline())
1756 {
1757 setUnderlineXoff( xoff);
1758 setMaxUnderline(iDrop);
1759 }
1760 else
1761 {
1762 setUnderlineXoff( P_Run->getUnderlineXoff());
1763 setMaxUnderline(UT_MAX( P_Run->getMaxUnderline(), iDrop));
1764 }
1765 }
1766 if (b_Overline)
1767 {
1768 iDrop = yoff + pG->tlu(1) + UT_MAX(pG->tlu(10),static_cast<UT_sint32>(getAscent()) - pG->tlu(10))/8;
1769 if(!P_Run->isOverline())
1770 {
1771 setOverlineXoff( xoff);
1772 setMinOverline(iDrop);
1773 }
1774 else
1775 {
1776 setOverlineXoff( P_Run->getOverlineXoff());
1777 setMinOverline(UT_MIN( P_Run->getMinOverline(), iDrop));
1778 }
1779 }
1780 }
1781 m_iLineWidth = getLinethickness();
1782 pG->setLineWidth(m_iLineWidth);
1783 /*
1784 If the next run returns NULL or if we are on the last run
1785 we've reached the of the line of text so the overlines and underlines must
1786 be drawn.
1787 */
1788 if(N_Run == NULL || b_Lastrun)
1789 {
1790 if ( b_Underline)
1791 {
1792 iDrop = UT_MAX( getMaxUnderline(), iDrop);
1793 UT_sint32 totx = getUnderlineXoff();
1794 painter.drawLine(totx, iDrop, xoff+getWidth(), iDrop);
1795 }
1796 if ( b_Overline)
1797 {
1798 iDrop = UT_MIN( getMinOverline(), iDrop);
1799 UT_sint32 totx = getOverlineXoff();
1800 painter.drawLine(totx, iDrop, xoff+getWidth(), iDrop);
1801 }
1802 }
1803 /*
1804 Otherwise look to see if the next run has an underline or overline
1805 if not, draw the line, if does mark the next run as dirty to make sure it
1806 is drawn later.
1807 */
1808 else
1809 {
1810 if ( b_Underline )
1811 {
1812 if(!N_Run->isUnderline() || isSelectionDraw())
1813 {
1814 iDrop = UT_MAX( getMaxUnderline(), iDrop);
1815 UT_sint32 totx = getUnderlineXoff();
1816 xxx_UT_DEBUGMSG(("Underlining y-logical %d \n",iDrop));
1817 painter.drawLine(totx, iDrop, xoff+getWidth(), iDrop);
1818 }
1819 else
1820 {
1821 N_Run->markAsDirty();
1822 }
1823 }
1824 if ( b_Overline )
1825 {
1826 if(!N_Run->isOverline() || isSelectionDraw())
1827 {
1828 iDrop = UT_MIN( getMinOverline(), iDrop);
1829 UT_sint32 totx = getOverlineXoff();
1830 painter.drawLine(totx, iDrop, xoff+getWidth(), iDrop);
1831 }
1832 else
1833 {
1834 N_Run->markAsDirty();
1835 }
1836 }
1837 }
1838 /*
1839 We always want strikethrough to go right through the middle of the
1840 text so we can keep the original code.
1841 */
1842 if ( b_Strikethrough)
1843 {
1844 iDrop = yoff + getAscent() * 2 / 3;
1845 painter.drawLine(xoff, iDrop, xoff+getWidth(), iDrop);
1846 }
1847 /*
1848 Restore the previous line width.
1849 */
1850 _setLineWidth(old_LineWidth);
1851 pG->setLineWidth(_getLineWidth());
1852 if(!b_Topline && !b_Bottomline)
1853 return;
1854 /*
1855 We always draw Topline right at the top of the line so there is no ambiguity
1856 */
1857 UT_sint32 ithick = getToplineThickness();
1858
1859 UT_RGBColor clrFG;
1860 const PP_AttrProp * pSpanAP = NULL;
1861 const PP_AttrProp * pBlockAP = NULL;
1862 const PP_AttrProp * pSectionAP = NULL;
1863
1864 PD_Document * pDoc = getBlock()->getDocument();
1865
1866 getSpanAP(pSpanAP);
1867 getBlockAP(pBlockAP);
1868 UT_parseColor(PP_evalProperty("color",pSpanAP,pBlockAP, pSectionAP, pDoc, true), clrFG);
1869
1870 // This gives the baseline of the selection.
1871 // need to clear full height of line, in case we had a selection
1872 // UT_sint32 xxoff=0 ,ybase =0;
1873 // getLine()->getScreenOffsets(this, xxoff, ybase);
1874
1875
1876 if ( b_Topline)
1877 {
1878 UT_sint32 ybase = yoff + getAscent() - getLine()->getAscent() + pG->tlu(1);
1879 painter.fillRect(clrFG, xoff, ybase, getWidth(), ithick);
1880 }
1881 /*
1882 We always draw bottomline right at the bottom so there is no ambiguity
1883 */
1884 if ( b_Bottomline)
1885 {
1886 painter.fillRect(clrFG, xoff, yoff+getLine()->getHeight()-ithick+pG->tlu(1), getWidth(), ithick);
1887 }
1888 }
1889
isUnderline(void) const1890 inline bool fp_Run::isUnderline(void) const
1891 {
1892 return ((m_fDecorations & TEXT_DECOR_UNDERLINE) != 0);
1893 }
1894
1895
isOverline(void) const1896 inline bool fp_Run::isOverline(void) const
1897 {
1898 return ((m_fDecorations & TEXT_DECOR_OVERLINE) != 0);
1899 }
1900
isStrikethrough(void) const1901 inline bool fp_Run::isStrikethrough(void) const
1902 {
1903 return ((m_fDecorations & TEXT_DECOR_LINETHROUGH) != 0);
1904 }
1905
1906
isTopline(void) const1907 inline bool fp_Run::isTopline(void) const
1908 {
1909 return ((m_fDecorations & TEXT_DECOR_TOPLINE) != 0);
1910 }
1911
1912
isBottomline(void) const1913 inline bool fp_Run::isBottomline(void) const
1914 {
1915 return ((m_fDecorations & TEXT_DECOR_BOTTOMLINE) != 0);
1916 }
1917
setLinethickness(UT_sint32 max_linethickness)1918 void fp_Run::setLinethickness(UT_sint32 max_linethickness)
1919 {
1920 m_iLinethickness = max_linethickness;
1921 }
1922
setUnderlineXoff(UT_sint32 xoff)1923 void fp_Run::setUnderlineXoff(UT_sint32 xoff)
1924 {
1925 m_iUnderlineXoff = xoff;
1926 }
1927
getUnderlineXoff(void) const1928 UT_sint32 fp_Run::getUnderlineXoff(void) const
1929 {
1930 return m_iUnderlineXoff;
1931 }
1932
setOverlineXoff(UT_sint32 xoff)1933 void fp_Run::setOverlineXoff(UT_sint32 xoff)
1934 {
1935 m_iOverlineXoff = xoff;
1936 }
1937
getOverlineXoff(void) const1938 UT_sint32 fp_Run::getOverlineXoff(void) const
1939 {
1940 return m_iOverlineXoff;
1941 }
1942
setMaxUnderline(UT_sint32 maxh)1943 void fp_Run::setMaxUnderline(UT_sint32 maxh)
1944 {
1945 m_imaxUnderline = maxh;
1946 }
1947
getMaxUnderline(void) const1948 UT_sint32 fp_Run::getMaxUnderline(void) const
1949 {
1950 return m_imaxUnderline;
1951 }
1952
setMinOverline(UT_sint32 minh)1953 void fp_Run::setMinOverline(UT_sint32 minh)
1954 {
1955 m_iminOverline = minh;
1956 }
1957
getMinOverline(void) const1958 UT_sint32 fp_Run::getMinOverline(void) const
1959 {
1960 return m_iminOverline;
1961 }
1962
getLinethickness(void) const1963 UT_sint32 fp_Run::getLinethickness( void) const
1964 {
1965 return m_iLinethickness;
1966 }
1967
getToplineThickness(void) const1968 UT_sint32 fp_Run::getToplineThickness(void) const
1969 {
1970 return UT_convertToLogicalUnits("0.8pt");
1971 }
1972
1973 /*!
1974 * This draws a line with some text in the center.
1975 * \param xOff the x offset of the left end of the line
1976 * \param yOff the y offset of the top (maybe bottom, I don't know) of
1977 * the line
1978 * \param iWidth the desired length of the line.
1979 * \param iHeight the desired height of the line. Note that the line
1980 * will almost certainly take up more vertical space than this, since
1981 * the text will be taller than the line.
1982 * \param pText the text to be displayed in the middle of the line
1983 * \bug Currently, this does not detect whether it is on the screen or
1984 * not, so it redraws way too often.
1985 */
_drawTextLine(UT_sint32 xoff,UT_sint32 yoff,UT_uint32 iWidth,UT_uint32 iHeight,UT_UCSChar * pText)1986 void fp_Run::_drawTextLine(UT_sint32 xoff,UT_sint32 yoff,UT_uint32 iWidth,UT_uint32 iHeight,UT_UCSChar *pText)
1987 {
1988 GR_Font *pFont = getGraphics()->getGUIFont();
1989
1990 GR_Painter painter(getGraphics());
1991 getGraphics()->setFont(pFont);
1992
1993 UT_uint32 iTextLen = UT_UCS4_strlen(pText);
1994 UT_uint32 iTextWidth = getGraphics()->measureString(pText,0,iTextLen,NULL);
1995 UT_uint32 iTextHeight = getGraphics()->getFontHeight(pFont);
1996
1997 UT_uint32 xoffText = xoff + (iWidth - iTextWidth) / 2;
1998 UT_uint32 yoffText = yoff - getGraphics()->getFontAscent(pFont) * 2 / 3;
1999
2000 painter.drawLine(xoff,yoff,xoff + iWidth,yoff);
2001
2002 if((iTextWidth < iWidth) && (iTextHeight < iHeight))
2003 {
2004 Fill(getGraphics(),xoffText,yoffText,iTextWidth,iTextHeight);
2005 painter.drawChars(pText,0,iTextLen,xoffText,yoffText);
2006 }
2007 }
2008
2009 //////////////////////////////////////////////////////////////////
2010 //////////////////////////////////////////////////////////////////
2011
fp_TabRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)2012 fp_TabRun::fp_TabRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen)
2013 : fp_Run(pBL, iOffsetFirst, iLen, FPRUN_TAB),
2014 m_leader(FL_LEADER_NONE),
2015 m_TabType(FL_TAB_NONE),
2016 m_bIsTOC(false),
2017 m_bIsTOCListLabel(false)
2018 {
2019 lookupProperties();
2020 }
2021
_lookupProperties(const PP_AttrProp * pSpanAP,const PP_AttrProp * pBlockAP,const PP_AttrProp * pSectionAP,GR_Graphics * pG)2022 void fp_TabRun::_lookupProperties(const PP_AttrProp * pSpanAP,
2023 const PP_AttrProp * pBlockAP,
2024 const PP_AttrProp * pSectionAP,
2025 GR_Graphics * pG)
2026 {
2027 bool bChanged = false;
2028
2029 fd_Field * fd = NULL;
2030 getBlock()->getField(getBlockOffset(),fd);
2031 _setField(fd);
2032 if(pG == NULL)
2033 {
2034 pG = getGraphics();
2035 }
2036 UT_RGBColor clrFG;
2037 UT_parseColor(PP_evalProperty("color",pSpanAP,pBlockAP,pSectionAP, getBlock()->getDocument(), true), clrFG);
2038 bChanged |= (clrFG != _getColorFG());
2039 _setColorFG(clrFG);
2040
2041 // look for fonts in this DocLayout's font cache
2042 FL_DocLayout * pLayout = getBlock()->getDocLayout();
2043 const GR_Font * pFont = pLayout->findFont(pSpanAP,pBlockAP,pSectionAP,getGraphics());
2044
2045 if (pFont != _getFont())
2046 {
2047 _setFont(pFont);
2048 _setAscent(pG->getFontAscent(pFont));
2049 _setDescent(pG->getFontDescent(pFont));
2050 _setHeight(pG->getFontHeight(pFont));
2051 bChanged = true;
2052 }
2053
2054 if(getDirection() != UT_BIDI_WS)
2055 {
2056 _setDirection(UT_BIDI_WS);
2057 bChanged = true;
2058 //setDirectionProperty(UT_BIDI_WS);
2059 }
2060 //
2061 // Lookup Decoration properties for this run
2062 //
2063 const gchar *pszDecor = PP_evalProperty("text-decoration",pSpanAP,pBlockAP,pSectionAP, getBlock()->getDocument(), true);
2064 _setLineWidth(getToplineThickness());
2065
2066 UT_uint32 oldDecors = _getDecorations();
2067 _setDecorations(0);
2068 gchar* p;
2069 if (!(p = g_strdup(pszDecor)))
2070 {
2071 // TODO outofmem
2072 }
2073 UT_ASSERT(p || !pszDecor);
2074 gchar* q = strtok(p, " ");
2075
2076 while (q)
2077 {
2078 if (0 == strcmp(q, "underline"))
2079 {
2080 _orDecorations(TEXT_DECOR_UNDERLINE);
2081 }
2082 else if (0 == strcmp(q, "overline"))
2083 {
2084 _orDecorations(TEXT_DECOR_OVERLINE);
2085 }
2086 else if (0 == strcmp(q, "line-through"))
2087 {
2088 _orDecorations(TEXT_DECOR_LINETHROUGH);
2089 }
2090 else if (0 == strcmp(q, "topline"))
2091 {
2092 _orDecorations(TEXT_DECOR_TOPLINE);
2093 }
2094 else if (0 == strcmp(q, "bottomline"))
2095 {
2096 _orDecorations(TEXT_DECOR_BOTTOMLINE);
2097 }
2098 q = strtok(NULL, " ");
2099 }
2100 g_free(p);
2101
2102 bChanged |= (oldDecors != _getDecorations());
2103
2104 if(bChanged)
2105 clearScreen();
2106
2107 }
2108
canBreakAfter(void) const2109 bool fp_TabRun::canBreakAfter(void) const
2110 {
2111 return false;
2112 }
2113
canBreakBefore(void) const2114 bool fp_TabRun::canBreakBefore(void) const
2115 {
2116 return false;
2117 }
2118
_letPointPass(void) const2119 bool fp_TabRun::_letPointPass(void) const
2120 {
2121 return true;
2122 }
2123
hasLayoutProperties(void) const2124 bool fp_TabRun::hasLayoutProperties(void) const
2125 {
2126 return true;
2127 }
2128
mapXYToPosition(UT_sint32 x,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)2129 void fp_TabRun::mapXYToPosition(UT_sint32 x, UT_sint32 /*y*/, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool& /*isTOC*/)
2130 {
2131 //TODO: Find everything that calls this and modify them to allow y-axis.
2132
2133
2134 // If X is left of the middle, return offset to the left,
2135 // otherwise the offset to the right.
2136 if (x < (getWidth() / 2))
2137 pos = getBlock()->getPosition() + getBlockOffset();
2138 else
2139 pos = getBlock()->getPosition() + getBlockOffset() + getLength();
2140
2141 bBOL = false;
2142 bEOL = false;
2143 }
2144
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)2145 void fp_TabRun::findPointCoords(UT_uint32 iOffset, UT_sint32& x, UT_sint32& y, UT_sint32& x2, UT_sint32& y2, UT_sint32& height, bool& bDirection)
2146 {
2147 //UT_DEBUGMSG(("fintPointCoords: TabRun\n"));
2148 UT_sint32 xoff;
2149 UT_sint32 yoff;
2150 UT_sint32 xoff2;
2151 UT_sint32 yoff2;
2152
2153 UT_ASSERT(getLine());
2154 if(getLine()->getY() == -2000000)
2155 {
2156 // UT_ASSERT(UT_SHOULD_NOT_HAPPEN); // might need this later
2157 }
2158 getLine()->getOffsets(this, xoff, yoff);
2159
2160 fp_Run * pRun = 0;
2161 UT_sint32 iNextDir = getVisDirection();
2162
2163 if (iOffset == (getBlockOffset() + getLength())) //#TF is this the right-most logical element of the run?
2164 {
2165 pRun = getNextRun();
2166 if(pRun)
2167 {
2168 pRun->getLine()->getOffsets(pRun, xoff2, yoff2);
2169 iNextDir = pRun->getVisDirection();
2170 }
2171 }
2172
2173 UT_sint32 iDirection = getVisDirection();
2174
2175 x = xoff;
2176
2177 if(iDirection == UT_BIDI_LTR)
2178 {
2179 xxx_UT_DEBUGMSG(("iOffset %d, getBlockOffset() %d, getLength() %d\n", iOffset,getBlockOffset(),getLength()));
2180 if(iOffset != getBlockOffset())
2181 {
2182 // this happens when a tab run is last run in a block and the eop's run
2183 //findPointCoords() is called ...
2184 //UT_ASSERT(iOffset == (getBlockOffset() + getLength()));
2185 x += getWidth();
2186 }
2187 }
2188 else
2189 {
2190 if(iOffset == getBlockOffset())
2191 {
2192 x += getWidth();
2193 }
2194 }
2195
2196
2197 if(pRun && (iNextDir != iDirection)) //if this run precedes run of different direction, we have to split the caret
2198 {
2199 x2 = (iNextDir == UT_BIDI_LTR) ? xoff + pRun->getWidth() : xoff2;
2200 y2 = yoff2;
2201 }
2202 else
2203 {
2204 x2 = x;
2205 y2 = yoff;
2206 }
2207
2208 bDirection = (iDirection != UT_BIDI_LTR);
2209 y = yoff;
2210 height = getHeight();
2211 }
2212
isTOCTab(void)2213 bool fp_TabRun::isTOCTab(void)
2214 {
2215 return m_bIsTOC;
2216 }
2217
2218
setTOCTabListLabel(void)2219 void fp_TabRun::setTOCTabListLabel(void)
2220 {
2221 m_bIsTOCListLabel = true;
2222 _setLength(0);
2223 m_leader = FL_LEADER_NONE;
2224 m_TabType = FL_TAB_LEFT;
2225 }
2226
setTabWidth(UT_sint32 iWidth)2227 void fp_TabRun::setTabWidth(UT_sint32 iWidth)
2228 {
2229 clearScreen();
2230 fp_Run::_setWidth(iWidth);
2231 }
2232
setLeader(eTabLeader iLeader)2233 void fp_TabRun::setLeader(eTabLeader iLeader)
2234 {
2235 clearScreen();
2236 m_leader = iLeader;
2237 }
2238
getLeader(void)2239 eTabLeader fp_TabRun::getLeader(void)
2240 {
2241 return m_leader;
2242 }
2243
2244
setTabType(eTabType iTabType)2245 void fp_TabRun::setTabType(eTabType iTabType)
2246 {
2247 m_TabType = iTabType;
2248 }
2249
getTabType(void) const2250 eTabType fp_TabRun::getTabType(void) const
2251 {
2252 return m_TabType;
2253 }
2254
2255
_clearScreen(bool)2256 void fp_TabRun::_clearScreen(bool /* bFullLineHeightRect */)
2257 {
2258 // UT_ASSERT(!isDirty());
2259 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
2260
2261 UT_sint32 xoff = 0, yoff = 0;
2262
2263 // need to clear full height of line, in case we had a selection
2264 getLine()->getScreenOffsets(this, xoff, yoff);
2265 Fill(getGraphics(),xoff, yoff, getWidth(), getLine()->getHeight());
2266 }
2267
_drawArrow(UT_uint32 iLeft,UT_uint32 iTop,UT_uint32 iWidth,UT_uint32)2268 void fp_TabRun::_drawArrow(UT_uint32 iLeft,UT_uint32 iTop,UT_uint32 iWidth, UT_uint32 /*iHeight*/)
2269 {
2270 if (!(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN))){
2271 return;
2272 }
2273
2274 #define NPOINTS 6
2275
2276 UT_Point points[NPOINTS];
2277
2278 UT_sint32 cur_linewidth = getGraphics()->tlu(1) + UT_MAX(getGraphics()->tlu(10),static_cast<UT_sint32>(getAscent()) - getGraphics()->tlu(10)) / 8;
2279 UT_uint32 iyAxis = iTop + getLine()->getAscent() * 2 / 3;
2280 UT_uint32 iMaxWidth = UT_MIN(iWidth / 10 * 6, static_cast<UT_uint32>(cur_linewidth) * 9);
2281 UT_uint32 ixGap = (iWidth - iMaxWidth) / 2;
2282
2283 //UT_DEBUGMSG(("iLeft %d, iWidth %d, visDir \"%s\"\n", iLeft,iWidth, getVisDirection() == UT_BIDI_LTR ? "ltr":"rtl"));
2284 if(getVisDirection() == UT_BIDI_LTR)
2285 {
2286 points[0].x = iLeft + ixGap + iMaxWidth - cur_linewidth * 4;
2287 points[0].y = iyAxis - cur_linewidth * 2;
2288
2289 points[1].x = points[0].x + cur_linewidth;
2290 points[1].y = points[0].y;
2291
2292 points[2].x = iLeft + iWidth - ixGap;
2293 points[2].y = iyAxis;
2294 }
2295 else
2296 {
2297 //iLeftAdj -= getWidth();
2298
2299 points[0].x = iLeft + ixGap + cur_linewidth * 4;
2300 points[0].y = iyAxis - cur_linewidth * 2;
2301
2302 points[1].x = points[0].x - cur_linewidth;
2303 points[1].y = points[0].y;
2304
2305 points[2].x = iLeft + ixGap;
2306 points[2].y = iyAxis;
2307
2308 }
2309
2310 points[3].x = points[1].x;
2311 points[3].y = iyAxis + cur_linewidth * 2;
2312
2313 points[4].x = points[0].x;
2314 points[4].y = points[3].y;
2315
2316 points[5].x = points[0].x;
2317 points[5].y = points[0].y;
2318
2319 GR_Painter painter(getGraphics());
2320
2321 UT_RGBColor clrShowPara(_getView()->getColorShowPara());
2322 painter.polygon(clrShowPara,points,NPOINTS);
2323
2324 xxx_UT_DEBUGMSG(("fp_TabRun::_drawArrow: iLeft %d, iyAxis %d, cur_linewidth %d, iMaxWidth %d\n",
2325 iLeft, iyAxis, cur_linewidth, iMaxWidth));
2326
2327 // only draw the rectangle if iMaxWidth - cur_linewidth * 4 > 0, otherwise
2328 // we get the rect running pass the end of the line and off the screen
2329 if(static_cast<UT_sint32>(iMaxWidth - cur_linewidth * 4) > 0)
2330 {
2331 if(getVisDirection() == UT_BIDI_LTR)
2332 {
2333 painter.fillRect(clrShowPara,iLeft + ixGap,iyAxis - cur_linewidth / 2,iMaxWidth - cur_linewidth * 4,cur_linewidth);
2334 }
2335 else
2336 {
2337 painter.fillRect(clrShowPara,iLeft + ixGap + cur_linewidth * 4,iyAxis - cur_linewidth / 2,iMaxWidth - cur_linewidth * 4,cur_linewidth);
2338 }
2339 }
2340 #undef NPOINTS
2341 }
2342
_draw(dg_DrawArgs * pDA)2343 void fp_TabRun::_draw(dg_DrawArgs* pDA)
2344 {
2345 xxx_UT_DEBUGMSG(("fp_TabRun::_draw (0x%x)\n",this));
2346 GR_Graphics * pG = pDA->pG;
2347
2348 // need to draw to the full height of line to join with line above.
2349 UT_sint32 xoff= 0, yoff=0, DA_xoff = pDA->xoff;
2350
2351 getLine()->getScreenOffsets(this, xoff, yoff);
2352
2353 // need to clear full height of line, in case we had a selection
2354
2355 UT_sint32 iFillHeight2 = getLine()->getHeight();
2356 UT_sint32 iFillTop = pDA->yoff - getLine()->getAscent();
2357
2358 xxx_UT_DEBUGMSG(("iFillTop Tab %d YTopOfRun %d \n",iFillTop, pDA->yoff - getAscent()));
2359 FV_View* pView = _getView();
2360 UT_uint32 iSelAnchor = pView->getSelectionAnchor();
2361 UT_uint32 iPoint = pView->getPoint();
2362
2363 UT_uint32 iSel1 = UT_MIN(iSelAnchor, iPoint);
2364 UT_uint32 iSel2 = UT_MAX(iSelAnchor, iPoint);
2365
2366 UT_ASSERT(iSel1 <= iSel2);
2367
2368 UT_uint32 iRunBase = getBlock()->getPosition() + getOffsetFirstVis(); //getBlockOffset();
2369
2370 UT_RGBColor clrFG;
2371 const PP_AttrProp * pSpanAP = NULL;
2372 const PP_AttrProp * pBlockAP = NULL;
2373 const PP_AttrProp * pSectionAP = NULL;
2374
2375 PD_Document * pDoc = getBlock()->getDocument();
2376
2377 getSpanAP(pSpanAP);
2378 getBlockAP(pBlockAP);
2379
2380 UT_parseColor(PP_evalProperty("color",pSpanAP,pBlockAP, pSectionAP, pDoc, true), clrFG);
2381
2382 GR_Painter painter(pG);
2383
2384 if (getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN) && (isInSelectedTOC() ||
2385 /* pView->getFocus()!=AV_FOCUS_NONE && */
2386 ((iSel1 <= iRunBase) && (iSel2 > iRunBase))) )
2387 {
2388 painter.fillRect(_getView()->getColorSelBackground(), /*pDA->xoff*/DA_xoff, iFillTop, getWidth(), iFillHeight2);
2389 if(pView->getShowPara()){
2390 _drawArrow(/*pDA->xoff*/DA_xoff, iFillTop, getWidth(), iFillHeight2);
2391 }
2392 }
2393 else
2394 {
2395 Fill(pG,DA_xoff, iFillTop, getWidth(), iFillHeight2);
2396 if(pView->getShowPara()){
2397 _drawArrow(/*pDA->xoff*/DA_xoff, iFillTop, getWidth(), iFillHeight2);
2398 }
2399 }
2400 if (m_leader != FL_LEADER_NONE)
2401 {
2402 UT_UCSChar tmp[151];
2403 UT_GrowBufElement wid[151];
2404 int i, cumWidth;
2405
2406 tmp[0] = 150;
2407 switch (m_leader)
2408 {
2409 case FL_LEADER_DOT:
2410 tmp[1] = '.';
2411 break;
2412 case FL_LEADER_HYPHEN:
2413 tmp[1] = '-';
2414 break;
2415 case FL_LEADER_UNDERLINE:
2416 tmp[1] = '_';
2417 break;
2418 default:
2419 tmp[1] = ' ';
2420 break;
2421 }
2422
2423 for (i = 2; i < 151; i++)
2424 tmp[i] = tmp[1];
2425
2426
2427 pG->setFont(_getFont());
2428 pG->measureString(tmp, 1, 150, wid);
2429 // one would think that one could measure
2430 // one character and divide the needed
2431 // width by that; would one be so wrong?
2432 // we're not dealing with different letters
2433 // here, after all.
2434
2435 i = 1;
2436 cumWidth = 0;
2437 FL_DocLayout * pLayout = getBlock()->getDocLayout();
2438 UT_sint32 iTabTop = pDA->yoff - getAscent();
2439 if(pG && pLayout->isQuickPrint() && pG->queryProperties(GR_Graphics::DGP_PAPER))
2440 {
2441 iTabTop = pDA->yoff - pG->getFontAscent(_getFont());
2442 }
2443 while (cumWidth < getWidth() && i < 151)
2444 {
2445 cumWidth += wid[i++];
2446 }
2447 i = (i>=3) ? i - 2 : 1;
2448 pG->setColor(clrFG);
2449 painter.drawChars(tmp, 1, i, /*pDA->xoff*/DA_xoff, iTabTop,wid);
2450 }
2451 //
2452 // Draw underline/overline/strikethough
2453 //
2454 UT_sint32 yTopOfRun = pDA->yoff - getAscent()-1; // Hack to remove
2455 //character dirt
2456 drawDecors( xoff, yTopOfRun,pG);
2457 //
2458 // Draw bar seperators
2459 //
2460 if(FL_TAB_BAR == getTabType())
2461 {
2462 // need to draw to the full height of line to join with line above.
2463 UT_sint32 iFillHeight = getLine()->getHeight();
2464 //
2465 // Scale the vertical line thickness for printers
2466 //
2467 UT_sint32 ithick = getToplineThickness();
2468 painter.fillRect(clrFG, /*pDA->xoff*/DA_xoff+getWidth()-ithick, iFillTop, ithick, iFillHeight);
2469 }
2470 }
2471
2472 //////////////////////////////////////////////////////////////////
2473 //////////////////////////////////////////////////////////////////
2474
fp_ForcedLineBreakRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)2475 fp_ForcedLineBreakRun::fp_ForcedLineBreakRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_Run(pBL, iOffsetFirst, iLen, FPRUN_FORCEDLINEBREAK)
2476 {
2477 //UT_DEBUGMSG(("fp_ForcedLineBreakRun constructor\n"));
2478 lookupProperties();
2479 }
2480
_lookupProperties(const PP_AttrProp * pSpanAP,const PP_AttrProp * pBlockAP,const PP_AttrProp * pSectionAP,GR_Graphics * pG)2481 void fp_ForcedLineBreakRun::_lookupProperties(const PP_AttrProp * pSpanAP,
2482 const PP_AttrProp * pBlockAP,
2483 const PP_AttrProp * pSectionAP,
2484 GR_Graphics * pG)
2485 {
2486 //UT_DEBUGMSG(("fp_ForcedLineBreakRun::lookupProperties\n"));
2487 fd_Field * fd = NULL;
2488 getBlock()->getField(getBlockOffset(),fd);
2489 _setField(fd);
2490 if(pG == NULL)
2491 {
2492 pG = getGraphics();
2493 }
2494 _inheritProperties();
2495 FV_View* pView = _getView();
2496 if (pView && pView->getShowPara())
2497 {
2498 //UT_UCSChar pEOP[] = { UCS_LINESEP, 0 }; - see bug 1279
2499 UT_UCSChar pEOP[] = { '^', 'l', 0 };
2500 UT_uint32 iTextLen = UT_UCS4_strlen(pEOP);
2501
2502 fp_Run* pPropRun = _findPrevPropertyRun();
2503 if (pPropRun && (FPRUN_TEXT == pPropRun->getType()))
2504 {
2505 fp_TextRun* pTextRun = static_cast<fp_TextRun*>(pPropRun);
2506 pG->setFont(pTextRun->getFont());
2507 }
2508 else
2509 {
2510 // look for fonts in this DocLayout's font cache
2511 FL_DocLayout * pLayout = getBlock()->getDocLayout();
2512
2513 const GR_Font * pFont = pLayout->findFont(pSpanAP,pBlockAP,pSectionAP,getGraphics());
2514 getGraphics()->setFont(pFont);
2515 }
2516 _setWidth(getGraphics()->measureString(pEOP, 0, iTextLen, NULL));
2517 xxx_UT_DEBUGMSG(("fp_EndOfParagraphRun::lookupProperties: width %d\n", getWidth()));
2518 }
2519 else
2520 {
2521 _setWidth(16);
2522 }
2523 }
2524
canBreakAfter(void) const2525 bool fp_ForcedLineBreakRun::canBreakAfter(void) const
2526 {
2527 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
2528
2529 return false;
2530 }
2531
canBreakBefore(void) const2532 bool fp_ForcedLineBreakRun::canBreakBefore(void) const
2533 {
2534 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
2535
2536 return false;
2537 }
2538
_letPointPass(void) const2539 bool fp_ForcedLineBreakRun::_letPointPass(void) const
2540 {
2541 return false;
2542 }
2543
mapXYToPosition(UT_sint32,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)2544 void fp_ForcedLineBreakRun::mapXYToPosition(UT_sint32 /* x */, UT_sint32 /*y*/, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool& /*isTOC*/)
2545 {
2546 //TODO: Find everything that calls this and modify them to allow x-axis and y-axis.
2547
2548 //UT_DEBUGMSG(("fp_ForcedLineBreakRun::mapXYToPosition\n"));
2549 pos = getBlock()->getPosition() + getBlockOffset();
2550 bBOL = false;
2551 bEOL = false;
2552 }
2553
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)2554 void fp_ForcedLineBreakRun::findPointCoords(UT_uint32 iOffset, UT_sint32& x, UT_sint32& y, UT_sint32& x2, UT_sint32& y2, UT_sint32& height, bool& bDirection)
2555 {
2556 // this assert is wrong -- a run can be asked to return coords for position it does
2557 // not contain if the run which contains it cannot contain point
2558 // UT_ASSERT(getBlockOffset() == iOffset || getBlockOffset()+1 == iOffset);
2559
2560 UT_sint32 xoff, yoff;
2561
2562 fp_Run* pPropRun = _findPrevPropertyRun();
2563
2564 if (pPropRun)
2565 {
2566 if(FPRUN_TEXT == pPropRun->getType())
2567 {
2568 pPropRun->findPointCoords(iOffset, x, y, x2, y2, height, bDirection);
2569 }
2570 else
2571 {
2572 height = getHeight();
2573 getLine()->getOffsets(this, xoff, yoff);
2574 x = xoff;
2575 y = yoff;
2576 }
2577 }
2578 else
2579 {
2580 height = getHeight();
2581 getLine()->getOffsets(this, xoff, yoff);
2582 x = xoff;
2583 y = yoff;
2584 }
2585
2586 if (iOffset == getBlockOffset()+1)
2587 {
2588 FV_View* pView = _getView();
2589 if (pView && pView->getShowPara())
2590 {
2591 x += getWidth();
2592 }
2593 }
2594
2595 x2 = x;
2596 y2 = y;
2597 //UT_DEBUGMSG(("fintPointCoords: ForcedLineBreakRun: x=%d, y=%d, h=%d\n", x,y,height));
2598 }
2599
_clearScreen(bool)2600 void fp_ForcedLineBreakRun::_clearScreen(bool /* bFullLineHeightRect */)
2601 {
2602 // UT_ASSERT(!isDirty());
2603 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
2604 }
2605
_draw(dg_DrawArgs * pDA)2606 void fp_ForcedLineBreakRun::_draw(dg_DrawArgs* pDA)
2607 {
2608
2609 UT_sint32 iXoffText = 0;
2610 UT_sint32 iYoffText = 0;
2611
2612 FV_View* pView = _getView();
2613 if(!pView || !pView->getShowPara())
2614 {
2615 if(getWidth())
2616 {
2617 _setWidth(0);
2618 }
2619 return;
2620 }
2621
2622 GR_Painter painter(getGraphics());
2623
2624 UT_uint32 iRunBase = getBlock()->getPosition() + getBlockOffset();
2625
2626 UT_uint32 iSelAnchor = pView->getSelectionAnchor();
2627 UT_uint32 iPoint = pView->getPoint();
2628
2629 UT_uint32 iSel1 = UT_MIN(iSelAnchor, iPoint);
2630 UT_uint32 iSel2 = UT_MAX(iSelAnchor, iPoint);
2631
2632 UT_ASSERT(iSel1 <= iSel2);
2633
2634 bool bIsSelected = false;
2635 if (/* pView->getFocus()!=AV_FOCUS_NONE && */ isInSelectedTOC() ||
2636 ((iSel1 <= iRunBase) && (iSel2 > iRunBase)))
2637 bIsSelected = true;
2638
2639 UT_RGBColor clrShowPara(pView->getColorShowPara());
2640
2641 //UT_UCSChar pEOP[] = { UCS_LINESEP, 0 };
2642 UT_UCSChar pEOP[] = { '^', 'l', 0 };
2643 UT_uint32 iTextLen = UT_UCS4_strlen(pEOP);
2644 UT_sint32 iAscent;
2645
2646 fp_Run* pPropRun = _findPrevPropertyRun();
2647 if (pPropRun && (FPRUN_TEXT == pPropRun->getType()))
2648 {
2649 fp_TextRun* pTextRun = static_cast<fp_TextRun*>(pPropRun);
2650 getGraphics()->setFont(pTextRun->getFont());
2651 iAscent = pTextRun->getAscent();
2652 }
2653 else
2654 {
2655 const PP_AttrProp * pSpanAP = NULL;
2656 const PP_AttrProp * pBlockAP = NULL;
2657 const PP_AttrProp * pSectionAP = NULL;
2658
2659 getSpanAP(pSpanAP);
2660 getBlockAP(pBlockAP);
2661
2662 // look for fonts in this DocLayout's font cache
2663 FL_DocLayout * pLayout = getBlock()->getDocLayout();
2664
2665 const GR_Font * pFont = pLayout->findFont(pSpanAP,pBlockAP,pSectionAP,getGraphics());
2666 getGraphics()->setFont(pFont);
2667 iAscent = getGraphics()->getFontAscent();
2668 }
2669
2670 // if we currently have a 0 width, i.e., we draw in response to the
2671 // showPara being turned on, then we obtain the new width, and then
2672 // tell the line to redo its layout and redraw instead of drawing ourselves
2673 // bool bWidthChange = false;
2674 // if(!getWidth())
2675 // bWidthChange = true;
2676
2677 _setWidth(getGraphics()->measureString(pEOP, 0, iTextLen, NULL));
2678 // if(bWidthChange)
2679 // {
2680 // getLine()->layout();
2681 // getLine()->redrawUpdate();
2682 // return;
2683 // }
2684
2685 _setHeight(getGraphics()->getFontHeight());
2686 iXoffText = pDA->xoff;
2687
2688 if(getBlock()->getDominantDirection() == UT_BIDI_RTL)
2689 {
2690 iXoffText -= getWidth();
2691 }
2692
2693 iYoffText = pDA->yoff - iAscent;
2694 xxx_UT_DEBUGMSG(("fp_EndOfParagraphRun::draw: width %d\n", getWidth()));
2695
2696 if (bIsSelected)
2697 {
2698 painter.fillRect(_getView()->getColorSelBackground(), iXoffText, iYoffText, getWidth(), getLine()->getHeight());
2699 }
2700 else
2701 {
2702 Fill(getGraphics(),iXoffText, iYoffText, getWidth(), getLine()->getHeight());
2703 }
2704 if (pView->getShowPara())
2705 {
2706 // Draw pilcrow
2707 getGraphics()->setColor(clrShowPara);
2708 painter.drawChars(pEOP, 0, iTextLen, iXoffText, iYoffText);
2709 }
2710 }
2711
2712 //////////////////////////////////////////////////////////////////
2713 //////////////////////////////////////////////////////////////////
2714
fp_FieldStartRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)2715 fp_FieldStartRun::fp_FieldStartRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_Run(pBL, iOffsetFirst, iLen, FPRUN_FIELDSTARTRUN)
2716 {
2717 lookupProperties();
2718 }
2719
_lookupProperties(const PP_AttrProp *,const PP_AttrProp *,const PP_AttrProp *,GR_Graphics *)2720 void fp_FieldStartRun::_lookupProperties(const PP_AttrProp * /*pSpanAP*/,
2721 const PP_AttrProp * /*pBlockAP*/,
2722 const PP_AttrProp * /*pSectionAP*/,
2723 GR_Graphics *)
2724 {
2725 fd_Field * fd = NULL;
2726 getBlock()->getField(getBlockOffset(),fd);
2727 _setField(fd);
2728 _setWidth(0);
2729 }
2730
canBreakAfter(void) const2731 bool fp_FieldStartRun::canBreakAfter(void) const
2732 {
2733 return true;
2734 }
2735
canBreakBefore(void) const2736 bool fp_FieldStartRun::canBreakBefore(void) const
2737 {
2738 return true;
2739 }
2740
_letPointPass(void) const2741 bool fp_FieldStartRun::_letPointPass(void) const
2742 {
2743 return true;
2744 }
2745
mapXYToPosition(UT_sint32,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)2746 void fp_FieldStartRun::mapXYToPosition(UT_sint32 /* x */, UT_sint32 /*y*/, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool& /*isTOC*/)
2747 {
2748 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
2749
2750 pos = getBlock()->getPosition() + getBlockOffset();
2751 bBOL = false;
2752 bEOL = false;
2753 }
2754
2755
findPointCoords(UT_uint32,UT_sint32 &,UT_sint32 &,UT_sint32 &,UT_sint32 &,UT_sint32 &,bool &)2756 void fp_FieldStartRun::findPointCoords(UT_uint32 /*iOffset*/, UT_sint32& /*x*/, UT_sint32& /*y*/, UT_sint32& /*x2*/, UT_sint32& /*y2*/, UT_sint32& /*height*/, bool& /*bDirection*/)
2757 {
2758 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
2759 }
2760
_clearScreen(bool)2761 void fp_FieldStartRun::_clearScreen(bool /* bFullLineHeightRect */)
2762 {
2763 // UT_ASSERT(!isDirty());
2764 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
2765 }
2766
_draw(dg_DrawArgs *)2767 void fp_FieldStartRun::_draw(dg_DrawArgs* /*pDA*/)
2768 {
2769
2770 }
2771
2772 //////////////////////////////////////////////////////////////////
2773 //////////////////////////////////////////////////////////////////
2774
fp_FieldEndRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)2775 fp_FieldEndRun::fp_FieldEndRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_Run(pBL, iOffsetFirst, iLen, FPRUN_FIELDENDRUN)
2776 {
2777 lookupProperties();
2778 }
2779
_lookupProperties(const PP_AttrProp *,const PP_AttrProp *,const PP_AttrProp *,GR_Graphics *)2780 void fp_FieldEndRun::_lookupProperties(const PP_AttrProp * /*pSpanAP*/,
2781 const PP_AttrProp * /*pBlockAP*/,
2782 const PP_AttrProp * /*pSectionAP*/,
2783 GR_Graphics *)
2784 {
2785 fd_Field * fd = NULL;
2786 getBlock()->getField(getBlockOffset(),fd);
2787 _setField(fd);
2788 _setWidth(0);
2789 }
2790
canBreakAfter(void) const2791 bool fp_FieldEndRun::canBreakAfter(void) const
2792 {
2793 return true;
2794 }
2795
canBreakBefore(void) const2796 bool fp_FieldEndRun::canBreakBefore(void) const
2797 {
2798 return true;
2799 }
2800
_letPointPass(void) const2801 bool fp_FieldEndRun::_letPointPass(void) const
2802 {
2803 return true;
2804 }
2805
mapXYToPosition(UT_sint32,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)2806 void fp_FieldEndRun::mapXYToPosition(UT_sint32 /* x */, UT_sint32 /*y*/, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool& /*isTOC*/)
2807 {
2808 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
2809
2810 pos = getBlock()->getPosition() + getBlockOffset();
2811 bBOL = false;
2812 bEOL = false;
2813 }
2814
findPointCoords(UT_uint32,UT_sint32 &,UT_sint32 &,UT_sint32 &,UT_sint32 &,UT_sint32 &,bool &)2815 void fp_FieldEndRun::findPointCoords(UT_uint32 /*iOffset*/, UT_sint32& /*x*/, UT_sint32& /*y*/, UT_sint32& /*x2*/, UT_sint32& /*y2*/, UT_sint32& /*height*/, bool& /*bDirection*/)
2816 {
2817 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
2818 }
2819
_clearScreen(bool)2820 void fp_FieldEndRun::_clearScreen(bool /* bFullLineHeightRect */)
2821 {
2822 // UT_ASSERT(!isDirty());
2823 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
2824 }
2825
_draw(dg_DrawArgs *)2826 void fp_FieldEndRun::_draw(dg_DrawArgs* /*pDA*/)
2827 {
2828
2829 }
2830
2831 //////////////////////////////////////////////////////////////////
2832 //////////////////////////////////////////////////////////////////
2833
2834
2835
fp_BookmarkRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)2836 fp_BookmarkRun::fp_BookmarkRun( fl_BlockLayout* pBL,
2837 UT_uint32 iOffsetFirst,
2838 UT_uint32 iLen)
2839 : fp_Run(pBL, iOffsetFirst, iLen, FPRUN_BOOKMARK)
2840 {
2841 m_pBookmark = getBlock()->getBookmark(iOffsetFirst);
2842 UT_return_if_fail(m_pBookmark);
2843
2844 _setDirty(true);
2845
2846 UT_ASSERT((pBL));
2847 _setDirection(UT_BIDI_WS);
2848
2849 m_bIsStart = (po_Bookmark::POBOOKMARK_START == m_pBookmark->getBookmarkType());
2850
2851 // have to cache the name, since we will need to use it for a while
2852 // after the associated PT fragment has been deleted.
2853 strncpy(m_pName, m_pBookmark->getName(), BOOKMARK_NAME_SIZE);
2854 m_pName[BOOKMARK_NAME_SIZE] = 0;
2855
2856 _setWidth(0);
2857 _setRecalcWidth(false);
2858 }
2859
isComrade(fp_BookmarkRun * pBR) const2860 bool fp_BookmarkRun::isComrade(fp_BookmarkRun *pBR) const
2861 {
2862 UT_ASSERT(m_pName && *m_pName && pBR->m_pName && *pBR->m_pName);
2863 return (0 == strcmp(m_pName, pBR->m_pName));
2864 }
2865
_lookupProperties(const PP_AttrProp *,const PP_AttrProp *,const PP_AttrProp *,GR_Graphics *)2866 void fp_BookmarkRun::_lookupProperties(const PP_AttrProp * /*pSpanAP*/,
2867 const PP_AttrProp * /*pBlockAP*/,
2868 const PP_AttrProp * /*pSectionAP*/,
2869 GR_Graphics *)
2870 {
2871 }
2872
canBreakAfter(void) const2873 bool fp_BookmarkRun::canBreakAfter(void) const
2874 {
2875 return true;
2876 }
2877
canBreakBefore(void) const2878 bool fp_BookmarkRun::canBreakBefore(void) const
2879 {
2880 return true;
2881 }
2882
_letPointPass(void) const2883 bool fp_BookmarkRun::_letPointPass(void) const
2884 {
2885 return true;
2886 }
2887
_canContainPoint(void) const2888 bool fp_BookmarkRun::_canContainPoint(void) const
2889 {
2890 return false;
2891 }
2892
_deleteFollowingIfAtInsPoint() const2893 bool fp_BookmarkRun::_deleteFollowingIfAtInsPoint() const
2894 {
2895 return true;
2896 }
2897
2898 /*!
2899 When working with bookmarks, the run block offset does not always adequately represent the
2900 location of the bookmark. For example, if the user bookmarks the same place in the doc with
2901 several bookmarks, the run offsets for each associated run will be different, but most of the
2902 time we are interested in the offset to the left or right of all stacked up bookmarks. Similarly,
2903 a bookmark that is immediately after a start of block needs to be treated in certain situations
2904 as if the block strux was also sellected. This function implements the necessary logic.
2905
2906 In general, when we jump to bookmarks, we go to the range in between the two bookmark
2907 object. However, for purposes of TOCs, we are interested in the range that is just outside the
2908 two objects.
2909
2910 \parameter bAfter: indicates if we want offset to the right (true) or left (false) of the
2911 bookmark
2912
2913 \return: the return value is document offset of the bookmarked position
2914 */
getBookmarkedDocPosition(bool bAfter) const2915 UT_uint32 fp_BookmarkRun::getBookmarkedDocPosition(bool bAfter) const
2916 {
2917 if(bAfter)
2918 {
2919 fp_Run * pRun = getNextRun();
2920 const fp_Run * pPrevRun = this;
2921
2922 while(pRun)
2923 {
2924 switch (pRun->getType())
2925 {
2926 case FPRUN_BOOKMARK:
2927 case FPRUN_FMTMARK:
2928 pPrevRun = pRun;
2929 pRun = pRun->getNextRun();
2930 break;
2931
2932 default:
2933 return getBlock()->getPosition(false) + pRun->getBlockOffset();
2934 }
2935 }
2936
2937 UT_ASSERT_HARMLESS( !pRun );
2938 return getBlock()->getPosition(false) + pPrevRun->getBlockOffset() + pPrevRun->getLength();
2939 }
2940 else
2941 {
2942 fp_Run * pRun = getPrevRun();
2943
2944 while(pRun)
2945 {
2946 switch (pRun->getType())
2947 {
2948 case FPRUN_BOOKMARK:
2949 case FPRUN_FMTMARK:
2950 pRun = pRun->getPrevRun();
2951 break;
2952
2953 default:
2954 return getBlock()->getPosition(false) + pRun->getBlockOffset() + pRun->getLength();
2955 }
2956 }
2957
2958 UT_ASSERT_HARMLESS( !pRun );
2959 return getBlock()->getPosition(true); // offset of the block strux
2960 }
2961 }
2962
mapXYToPosition(UT_sint32 x,UT_sint32 y,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool & isTOC)2963 void fp_BookmarkRun::mapXYToPosition(UT_sint32 x, UT_sint32 y, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool &isTOC)
2964 {
2965 fp_Run *pRun = getNextRun();
2966 UT_ASSERT(pRun);
2967 pRun->mapXYToPosition(x, y, pos, bBOL, bEOL,isTOC);
2968 }
2969
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)2970 void fp_BookmarkRun::findPointCoords(UT_uint32 iOffset, UT_sint32& x, UT_sint32& y, UT_sint32& x2, UT_sint32& y2, UT_sint32& height, bool& bDirection)
2971 {
2972 fp_Run * pRun = getNextRun();
2973 UT_ASSERT(pRun);
2974
2975 pRun->findPointCoords(iOffset, x, y, x2, y2, height, bDirection);
2976 }
2977
_clearScreen(bool)2978 void fp_BookmarkRun::_clearScreen(bool /* bFullLineHeightRect */)
2979 {
2980 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
2981
2982 FV_View* pView = _getView();
2983 if(!pView || !pView->getShowPara())
2984 {
2985 return;
2986 }
2987
2988
2989 UT_sint32 xoff = 0, yoff = 0;
2990 getLine()->getScreenOffsets(this, xoff, yoff);
2991
2992 if(m_bIsStart)
2993 Fill(getGraphics(), xoff, yoff, 4, 8);
2994 else
2995 Fill(getGraphics(),xoff - 4, yoff, 4, 8);
2996
2997 }
2998
_draw(dg_DrawArgs * pDA)2999 void fp_BookmarkRun::_draw(dg_DrawArgs* pDA)
3000 {
3001 GR_Graphics * pG = pDA->pG;
3002 if (!(pG->queryProperties(GR_Graphics::DGP_SCREEN))){
3003 return;
3004 }
3005
3006 FV_View* pView = _getView();
3007 if(!pView || !pView->getShowPara())
3008 {
3009 return;
3010 }
3011
3012 pG->setColor(_getView()->getColorShowPara());
3013
3014 #define NPOINTS 4
3015
3016 UT_Point points[NPOINTS];
3017
3018 points[0].y = pDA->yoff;
3019
3020
3021 if(m_bIsStart)
3022 {
3023 points[0].x = pDA->xoff - 4;
3024 points[1].x = pDA->xoff;
3025 }
3026 else
3027 {
3028 points[0].x = pDA->xoff;
3029 points[1].x = points[0].x - 4;
3030 }
3031
3032 points[1].y = points[0].y + 4;
3033
3034 points[2].x = points[0].x;
3035 points[2].y = points[0].y + 8;
3036
3037 points[3].x = points[0].x;
3038 points[3].y = points[0].y;
3039
3040 UT_RGBColor clrShowPara(_getView()->getColorShowPara());
3041
3042 GR_Painter painter(pG);
3043 painter.polygon(clrShowPara,points,NPOINTS);
3044 #undef NPOINTS
3045
3046 }
3047
3048 //////////////////////////////////////////////////////////////////
3049 //////////////////////////////////////////////////////////////////
3050
fp_HyperlinkRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32)3051 fp_HyperlinkRun::fp_HyperlinkRun( fl_BlockLayout* pBL,
3052 UT_uint32 iOffsetFirst,
3053 UT_uint32 /*iLen*/)
3054 : fp_Run(pBL, iOffsetFirst, 1, FPRUN_HYPERLINK)
3055 , m_bIsStart(false)
3056 , m_pTarget(NULL)
3057 , m_pTitle(NULL)
3058 {
3059 _setLength(1);
3060 _setDirty(false);
3061 _setWidth(0);
3062 _setRecalcWidth(false);
3063
3064 UT_ASSERT((pBL));
3065 _setDirection(UT_BIDI_WS);
3066
3067 _setTargetFromAPAttribute( "xlink:href");
3068 _setTitleFromAPAttribute( "xlink:title");
3069 }
3070
3071
~fp_HyperlinkRun()3072 fp_HyperlinkRun::~fp_HyperlinkRun()
3073 {
3074 DELETEPV(m_pTarget);
3075 DELETEPV(m_pTitle);
3076 }
3077
_lookupProperties(const PP_AttrProp *,const PP_AttrProp *,const PP_AttrProp *,GR_Graphics *)3078 void fp_HyperlinkRun::_lookupProperties(const PP_AttrProp * /*pSpanAP*/,
3079 const PP_AttrProp * /*pBlockAP*/,
3080 const PP_AttrProp * /*pSectionAP*/,
3081 GR_Graphics *)
3082 {
3083 }
3084
canBreakAfter(void) const3085 bool fp_HyperlinkRun::canBreakAfter(void) const
3086 {
3087 return false;
3088 }
3089
canBreakBefore(void) const3090 bool fp_HyperlinkRun::canBreakBefore(void) const
3091 {
3092 return true;
3093 }
3094
_letPointPass(void) const3095 bool fp_HyperlinkRun::_letPointPass(void) const
3096 {
3097 return true;
3098 }
3099
_canContainPoint(void) const3100 bool fp_HyperlinkRun::_canContainPoint(void) const
3101 {
3102 return false;
3103 }
3104
_deleteFollowingIfAtInsPoint() const3105 bool fp_HyperlinkRun::_deleteFollowingIfAtInsPoint() const
3106 {
3107 return true;
3108 }
3109
mapXYToPosition(UT_sint32 x,UT_sint32 y,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool & isTOC)3110 void fp_HyperlinkRun::mapXYToPosition(UT_sint32 x, UT_sint32 y, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool &isTOC)
3111 {
3112 fp_Run *pRun = getNextRun();
3113 UT_ASSERT(pRun);
3114 pRun->mapXYToPosition(x, y, pos, bBOL, bEOL,isTOC);
3115 }
3116
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)3117 void fp_HyperlinkRun::findPointCoords(UT_uint32 iOffset, UT_sint32& x, UT_sint32& y, UT_sint32& x2, UT_sint32& y2, UT_sint32& height, bool& bDirection)
3118 {
3119 fp_Run * pRun = getNextRun();
3120 UT_ASSERT(pRun);
3121
3122 pRun->findPointCoords(iOffset, x, y, x2, y2, height, bDirection);
3123 }
3124
_clearScreen(bool)3125 void fp_HyperlinkRun::_clearScreen(bool /* bFullLineHeightRect */)
3126 {
3127 }
3128
_draw(dg_DrawArgs *)3129 void fp_HyperlinkRun::_draw(dg_DrawArgs* /*pDA*/)
3130 {
3131 }
3132
_setTargetFromAPAttribute(const gchar * pAttrName)3133 void fp_HyperlinkRun::_setTargetFromAPAttribute( const gchar* pAttrName )
3134 {
3135 const PP_AttrProp * pAP = NULL;
3136
3137 getSpanAP(pAP);
3138
3139 const gchar * pTarget;
3140 const gchar * pName;
3141 bool bFound = false;
3142 UT_uint32 k = 0;
3143
3144 while(pAP->getNthAttribute(k++, pName, pTarget))
3145 {
3146 bFound = (0 == g_ascii_strncasecmp(pName,pAttrName,strlen(pAttrName)));
3147 if(bFound)
3148 break;
3149 }
3150
3151 // we have got to keep a local copy, since the pointer we get
3152 // is to a potentially volatile location
3153 if(bFound)
3154 {
3155 _setTarget( pTarget );
3156 m_bIsStart = true;
3157 //if this is a start of the hyperlink, we set m_pHyperlink to this,
3158 //so that when a run gets inserted after this one, its m_pHyperlink is
3159 //set correctly
3160 _setHyperlink(this);
3161 }
3162 else
3163 {
3164 m_bIsStart = false;
3165 m_pTarget = NULL;
3166 _setHyperlink(NULL);
3167 }
3168 }
3169
_setTitleFromAPAttribute(const gchar * pAttrName)3170 void fp_HyperlinkRun::_setTitleFromAPAttribute( const gchar* pAttrName )
3171 {
3172 const PP_AttrProp * pAP = NULL;
3173 getSpanAP(pAP);
3174
3175 const gchar *pTitle;
3176 if (pAP->getAttribute(pAttrName, pTitle))
3177 {
3178 _setTitle(pTitle);
3179 } else
3180 {
3181 m_pTitle = NULL;
3182 }
3183 }
3184
_setTarget(const gchar * pTarget)3185 void fp_HyperlinkRun::_setTarget( const gchar * pTarget )
3186 {
3187 DELETEPV(m_pTarget);
3188 UT_uint32 iTargetLen = strlen(pTarget);
3189 m_pTarget = new gchar [iTargetLen + 1];
3190 strncpy(m_pTarget, pTarget, iTargetLen + 1);
3191 }
3192
_setTitle(const gchar * pTitle)3193 void fp_HyperlinkRun::_setTitle( const gchar * pTitle )
3194 {
3195 DELETEPV(m_pTitle);
3196 UT_uint32 iTitleLen = strlen(pTitle);
3197 m_pTitle = new gchar [iTitleLen + 1];
3198 strncpy(m_pTitle, pTitle, iTitleLen + 1);
3199 }
3200
3201
3202 //////////////////////////////////////////////////////////////////
3203 //////////////////////////////////////////////////////////////////
fp_EndOfParagraphRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)3204 fp_EndOfParagraphRun::fp_EndOfParagraphRun(fl_BlockLayout* pBL,
3205 UT_uint32 iOffsetFirst,
3206 UT_uint32 iLen)
3207 : fp_Run(pBL, iOffsetFirst, iLen, FPRUN_ENDOFPARAGRAPH)
3208 {
3209
3210 _setLength(1);
3211 _setDirty(true);
3212 xxx_UT_DEBUGMSG(("fp_EndOfParagraphRun::created this %x block %x \n",this,getBlock()));
3213
3214 UT_ASSERT((pBL));
3215 _setDirection(pBL->getDominantDirection());
3216 lookupProperties();
3217 }
3218
3219
_recalcWidth(void)3220 bool fp_EndOfParagraphRun::_recalcWidth(void)
3221 {
3222 return false;
3223 }
3224
_lookupProperties(const PP_AttrProp * pSpanAP,const PP_AttrProp * pBlockAP,const PP_AttrProp * pSectionAP,GR_Graphics * pG)3225 void fp_EndOfParagraphRun::_lookupProperties(const PP_AttrProp * pSpanAP,
3226 const PP_AttrProp * pBlockAP,
3227 const PP_AttrProp * pSectionAP,
3228 GR_Graphics * pG)
3229 {
3230 xxx_UT_DEBUGMSG(("fp_EndOfParagraphRun::lookupProperties this %x block %x \n",this,getBlock()));
3231 _inheritProperties();
3232 xxx_UT_DEBUGMSG(("After Inherit props Height is %d \n",getHeight()));
3233 const gchar* pRevision = NULL;
3234
3235 if(pBlockAP && pBlockAP->getAttribute("revision", pRevision))
3236 {
3237 // we will not in fact be doing anything with the actual
3238 // properties and attributes contained in the revision
3239 // we just need its representation so the base class can
3240 // handle us properly
3241 PP_RevisionAttr * pRev = getRevisions();
3242 DELETEP(pRev);
3243
3244 _setRevisions(new PP_RevisionAttr(pRevision));
3245 }
3246
3247 FV_View* pView = _getView();
3248 if(pG == NULL)
3249 {
3250 pG = getGraphics();
3251 }
3252 if (pView && pView->getShowPara())
3253 {
3254 // Find width of Pilcrow
3255 UT_UCSChar pEOP[] = { UCS_PILCROW, 0 };
3256 UT_uint32 iTextLen = UT_UCS4_strlen(pEOP);
3257
3258 fp_Run* pPropRun = _findPrevPropertyRun();
3259 if (pPropRun && (FPRUN_TEXT == pPropRun->getType()))
3260 {
3261 fp_TextRun* pTextRun = static_cast<fp_TextRun*>(pPropRun);
3262 pG->setFont(pTextRun->getFont());
3263 }
3264 else
3265 {
3266 // look for fonts in this DocLayout's font cache
3267 FL_DocLayout * pLayout = getBlock()->getDocLayout();
3268
3269 const GR_Font * pFont = pLayout->findFont(pSpanAP,pBlockAP,pSectionAP,getGraphics());
3270 pG->setFont(pFont);
3271 }
3272 m_iDrawWidth = pG->measureString(pEOP, 0, iTextLen, NULL);
3273 xxx_UT_DEBUGMSG(("fp_EndOfParagraphRun::lookupProperties: width %d\n", getWidth()));
3274 }
3275 else
3276 {
3277 // FIXME:jskov This should probably be the width of the
3278 // document to the right of the pilcrow, see Paul's suggested
3279 // selection behaviors. Doesn't matter until we get selection
3280 // support though (which requires PT changes).
3281
3282 // I have changed this to 0, because otherwise it figures in
3283 // calculation of line width, and the last line in righ-aligned
3284 // paragraphs is shifted by the width of the pilcrow.
3285 // this required some additional changes to the _draw function
3286 // Tomas
3287 m_iDrawWidth = 0;
3288 }
3289 }
3290
canBreakAfter(void) const3291 bool fp_EndOfParagraphRun::canBreakAfter(void) const
3292 {
3293 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
3294
3295 return false;
3296 }
3297
canBreakBefore(void) const3298 bool fp_EndOfParagraphRun::canBreakBefore(void) const
3299 {
3300 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
3301
3302 return false;
3303 }
3304
_letPointPass(void) const3305 bool fp_EndOfParagraphRun::_letPointPass(void) const
3306 {
3307 return false;
3308 }
3309
mapXYToPosition(UT_sint32,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)3310 void fp_EndOfParagraphRun::mapXYToPosition(UT_sint32 /* x */, UT_sint32 /*y*/, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool& /*isTOC*/)
3311 {
3312 //TODO: Find everything that calls this and modify them to allow y-axis. (I think?)
3313 pos = getBlock()->getPosition() + getBlockOffset();
3314 bBOL = false;
3315 bEOL = true;
3316 }
3317
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)3318 void fp_EndOfParagraphRun::findPointCoords(UT_uint32 iOffset,
3319 UT_sint32& x, UT_sint32& y,
3320 UT_sint32& x2, UT_sint32& y2,
3321 UT_sint32& height,
3322 bool& bDirection)
3323 {
3324 // FIXME:jskov Find out why we are sometimes asked to find pos at
3325 // right of pilcrow. Should never ever happen... But does.
3326 // fjsdkjfklsd<forced-column-break>sdfsdsd move cursor back
3327 // UT_ASSERT(getBlockOffset() == iOffset);
3328
3329 fp_Run* pPropRun = _findPrevPropertyRun();
3330
3331 height = getHeight();
3332 if(pPropRun && pPropRun->getType() == FPRUN_IMAGE)
3333 {
3334 height = static_cast<fp_ImageRun *>(pPropRun)->getPointHeight();
3335 }
3336 xxx_UT_DEBUGMSG((" Got initial height of %d \n",height));
3337 if (pPropRun)
3338 {
3339 xxx_UT_DEBUGMSG(("Got propRun in EOPRun \n"));
3340 height = pPropRun->getHeight();
3341 if(pPropRun->getType() == FPRUN_IMAGE)
3342 {
3343 height = static_cast<fp_ImageRun *>(pPropRun)->getPointHeight();
3344 }
3345
3346 // If property Run is on the same line, get y location from
3347 // it (to reflect proper ascent).
3348 if (pPropRun->getLine() == getLine())
3349 {
3350 pPropRun->findPointCoords(iOffset, x, y, x2, y2, height, bDirection);
3351 xxx_UT_DEBUGMSG(("Got propRun in EOPRun inherited height %d \n",height));
3352 if(pPropRun->getType() == FPRUN_IMAGE)
3353 {
3354 height = static_cast<fp_ImageRun *>(pPropRun)->getPointHeight();
3355 }
3356 return;
3357 }
3358 }
3359 xxx_UT_DEBUGMSG((" Got final height of %d \n",height));
3360
3361 getLine()->getOffsets(this, x, y);
3362 x2 = x;
3363 y2 = y;
3364 }
3365
_clearScreen(bool)3366 void fp_EndOfParagraphRun::_clearScreen(bool /* bFullLineHeightRect */)
3367 {
3368 // UT_ASSERT(!isDirty());
3369 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
3370 if(m_iDrawWidth == 0 )
3371 {
3372 return;
3373 }
3374 UT_sint32 xoff = 0, yoff = 0;
3375 getLine()->getScreenOffsets(this, xoff, yoff);
3376
3377 if(getBlock()->getDominantDirection() == UT_BIDI_RTL)
3378 {
3379 xoff -= m_iDrawWidth;
3380 }
3381 Fill(getGraphics(),xoff, yoff+1, m_iDrawWidth, getLine()->getHeight()+1);
3382 }
3383
3384 /*!
3385 Draw end-of-paragraph Run graphical representation
3386 \param pDA Draw arguments
3387 Draws the pilcrow character (reverse P) in show paragraphs mode.
3388 \fixme Make it use the same typeface as preceding text.
3389 \note This _draw function is special in that it does (partly) lookup
3390 as well. That's because the pilcrow's typeface is controlled by the
3391 preceding character. Eventually, when the PT learns about EOP, it
3392 should be possible to just deal with this in the lookup function.
3393 */
_draw(dg_DrawArgs * pDA)3394 void fp_EndOfParagraphRun::_draw(dg_DrawArgs* pDA)
3395 {
3396 // if showPara is turned off we will not draw anything at all; however,
3397 // we will ensure that the width is set to 0, and if it is currently not
3398 // we will get our line to redo its layout and redraw.
3399 FV_View* pView = _getView();
3400 if(!pView || !pView->getShowPara())
3401 {
3402 if(m_iDrawWidth)
3403 {
3404 m_iDrawWidth = 0;
3405 //getLine()->layout();
3406 //getLine()->redrawUpdate();
3407 }
3408 return;
3409 }
3410
3411 UT_uint32 iRunBase = getBlock()->getPosition() + getBlockOffset();
3412
3413 UT_uint32 iSelAnchor = pView->getSelectionAnchor();
3414 UT_uint32 iPoint = pView->getPoint();
3415
3416 UT_uint32 iSel1 = UT_MIN(iSelAnchor, iPoint);
3417 UT_uint32 iSel2 = UT_MAX(iSelAnchor, iPoint);
3418
3419 UT_ASSERT(iSel1 <= iSel2);
3420
3421 bool bIsSelected = false;
3422 if (/* pView->getFocus()!=AV_FOCUS_NONE && */isInSelectedTOC() ||
3423 ((iSel1 <= iRunBase) && (iSel2 > iRunBase)))
3424 bIsSelected = true;
3425
3426 GR_Painter painter(getGraphics());
3427
3428 UT_UCSChar pEOP[] = { UCS_PILCROW, 0 };
3429 UT_uint32 iTextLen = UT_UCS4_strlen(pEOP);
3430 UT_sint32 iAscent;
3431
3432 fp_Run* pPropRun = _findPrevPropertyRun();
3433 if (pPropRun && (FPRUN_TEXT == pPropRun->getType()))
3434 {
3435 fp_TextRun* pTextRun = static_cast<fp_TextRun*>(pPropRun);
3436 getGraphics()->setFont(pTextRun->getFont());
3437 iAscent = pTextRun->getAscent();
3438 }
3439 else
3440 {
3441 const PP_AttrProp * pSpanAP = NULL;
3442 const PP_AttrProp * pBlockAP = NULL;
3443 const PP_AttrProp * pSectionAP = NULL;
3444
3445 getSpanAP(pSpanAP);
3446 getBlockAP(pBlockAP);
3447
3448 // look for fonts in this DocLayout's font cache
3449 FL_DocLayout * pLayout = getBlock()->getDocLayout();
3450
3451 const GR_Font * pFont = pLayout->findFont(pSpanAP,pBlockAP,pSectionAP,getGraphics());
3452 getGraphics()->setFont(pFont);
3453 iAscent = getGraphics()->getFontAscent();
3454 }
3455
3456 // if we currently have a 0 width, i.e., we draw in response to the
3457 // showPara being turned on, then we obtain the new width, and then
3458 // tell the line to redo its layout and redraw instead of drawing ourselves
3459 // bool bWidthChange = false;
3460 // if(!m_iDrawWidth)
3461 // bWidthChange = true;
3462
3463 m_iDrawWidth = getGraphics()->measureString(pEOP, 0, iTextLen, NULL);
3464 // if(bWidthChange)
3465 // {
3466 // getLine()->layout();
3467 // getLine()->redrawUpdate();
3468 // return;
3469 // }
3470
3471 _setHeight(getGraphics()->getFontHeight());
3472 m_iXoffText = pDA->xoff;
3473
3474 if(getBlock()->getDominantDirection() == UT_BIDI_RTL)
3475 {
3476 m_iXoffText -= m_iDrawWidth;
3477 }
3478
3479 m_iYoffText = pDA->yoff - iAscent;
3480 xxx_UT_DEBUGMSG(("fp_EndOfParagraphRun::draw: width %d\n", m_iDrawWidth));
3481
3482 if (bIsSelected)
3483 {
3484 painter.fillRect(_getView()->getColorSelBackground(), m_iXoffText, m_iYoffText, m_iDrawWidth, getLine()->getHeight());
3485 }
3486 else
3487 {
3488 Fill(getGraphics(),m_iXoffText, m_iYoffText, m_iDrawWidth, getLine()->getHeight());
3489 }
3490 if (getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN) && pView->getShowPara())
3491 {
3492 // Draw pilcrow
3493 // use the hard-coded colour only if not revised
3494 if(!getRevisions() || !pView->isShowRevisions())
3495 getGraphics()->setColor(pView->getColorShowPara());
3496 painter.drawChars(pEOP, 0, iTextLen, m_iXoffText, m_iYoffText);
3497 }
3498 }
3499
3500 //////////////////////////////////////////////////////////////////
3501 //////////////////////////////////////////////////////////////////
3502
3503
fp_ImageRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen,FG_Graphic * pFG,pf_Frag_Object * oh)3504 fp_ImageRun::fp_ImageRun(fl_BlockLayout* pBL,
3505 UT_uint32 iOffsetFirst,
3506 UT_uint32 iLen, FG_Graphic * pFG,
3507 pf_Frag_Object* oh) :
3508 fp_Run(pBL, iOffsetFirst, iLen, FPRUN_IMAGE),
3509 m_pFGraphic(pFG),
3510 m_iPointHeight(0),
3511 m_pSpanAP(NULL),
3512 m_bImageForPrinter (false),
3513 m_OH(oh)
3514 {
3515 #if 0 // put this back later
3516 UT_ASSERT(pImage);
3517 #endif
3518
3519 m_pImage = pFG->generateImage(getGraphics(), NULL, 0, 0);
3520 m_sCachedWidthProp = pFG->getWidthProp();
3521 m_sCachedHeightProp = pFG->getHeightProp();
3522 m_iGraphicTick = pBL->getDocLayout()->getGraphicTick();
3523 lookupProperties();
3524 }
3525
~fp_ImageRun()3526 fp_ImageRun::~fp_ImageRun()
3527 {
3528 DELETEP(m_pImage);
3529 DELETEP(m_pFGraphic);
3530 }
3531
regenerateImage(GR_Graphics * pG)3532 void fp_ImageRun::regenerateImage(GR_Graphics * pG)
3533 {
3534 DELETEP(m_pImage);
3535 m_pImage = m_pFGraphic->regenerateImage(pG);
3536 m_bImageForPrinter = pG->queryProperties(GR_Graphics::DGP_PAPER);
3537 m_iGraphicTick = getBlock()->getDocLayout()->getGraphicTick();
3538
3539 }
3540
_lookupProperties(const PP_AttrProp * pSpanAP,const PP_AttrProp *,const PP_AttrProp *,GR_Graphics * pG)3541 void fp_ImageRun::_lookupProperties(const PP_AttrProp * pSpanAP,
3542 const PP_AttrProp * /*pBlockAP*/,
3543 const PP_AttrProp * /*pSectionAP*/,
3544 GR_Graphics * pG)
3545 {
3546 fd_Field * fd = NULL;
3547 UT_return_if_fail(pSpanAP);
3548 m_pSpanAP = pSpanAP;
3549 getBlock()->getField(getBlockOffset(), fd);
3550 _setField(fd);
3551 const gchar * szWidth = NULL;
3552 pSpanAP->getProperty("width", szWidth);
3553 if(szWidth == NULL)
3554 {
3555 szWidth = "0in";
3556 }
3557 const gchar * szHeight = NULL;
3558 pSpanAP->getProperty("height", szHeight);
3559 if(pG == NULL)
3560 {
3561 pG = getGraphics();
3562 }
3563 if(szHeight == NULL)
3564 {
3565 szHeight = "0in";
3566 }
3567 UT_DEBUGMSG(("Orig szHeight = %s \n",szHeight));
3568 // Also get max width, height ready for generateImage.
3569
3570 fl_DocSectionLayout * pDSL = getBlock()->getDocSectionLayout();
3571 UT_sint32 maxW = static_cast<UT_sint32>(static_cast<double>(pDSL->getActualColumnWidth()));
3572 UT_sint32 maxH = static_cast<UT_sint32>(static_cast<double>(pDSL->getActualColumnHeight()));
3573 fl_ContainerLayout * pCL = getBlock()->myContainingLayout();
3574 if(pCL && pCL->getContainerType() == FL_CONTAINER_FRAME)
3575 {
3576 fl_FrameLayout * pFL = static_cast<fl_FrameLayout *>(pCL);
3577 maxW = pFL->getFrameWidth();
3578 maxH = pFL->getFrameHeight();
3579 if(getLine())
3580 {
3581 maxH -= getLine()->getY(); // take Y height into account.
3582 }
3583 }
3584 else if (pCL && pCL->getContainerType() == FL_CONTAINER_CELL)
3585 {
3586 //
3587 // Don't shrink images to fit cells. Cells should expand to fit images
3588 // This is a compromize that makes tables sane for insanely large
3589 // images. The user will have to adjust images size manually
3590 //
3591 maxW = static_cast<UT_sint32>(static_cast<double>(maxW));
3592 maxH = static_cast<UT_sint32>(static_cast<double>(maxH));
3593 }
3594 if(pG->tdu(maxW) < 3)
3595 {
3596 maxW = pG->tlu(3);
3597 }
3598 if(pG->tdu(maxH) < 3)
3599 {
3600 maxH = pG->tlu(3);
3601 }
3602 UT_DEBUGMSG(("Image szWidth %s Image szHeight %s \n",szWidth,szHeight));
3603 if((pG->queryProperties(GR_Graphics::DGP_PAPER) != m_bImageForPrinter) ||
3604 (strcmp(m_sCachedWidthProp.c_str(),szWidth) != 0) ||
3605 (strcmp(m_sCachedHeightProp.c_str(),szHeight) != 0) ||
3606 UT_convertToLogicalUnits(szHeight) > maxH ||
3607 UT_convertToLogicalUnits(szWidth) > maxW)
3608 {
3609 m_sCachedWidthProp = szWidth;
3610 m_sCachedHeightProp = szHeight;
3611 DELETEP(m_pImage);
3612 UT_sint32 iH = UT_convertToLogicalUnits(szHeight);
3613 UT_sint32 iW = UT_convertToLogicalUnits(szWidth);
3614 if((iW < maxW) && (iW > 30))
3615 {
3616 maxW = iW;
3617 UT_DEBUGMSG(("Change Image Width to %d \n",maxW));
3618 }
3619 if((iH < maxH) && (iH > 30))
3620 {
3621 maxH = iH;
3622 UT_DEBUGMSG(("Change Image Height to %d \n",maxH));
3623 }
3624 m_pImage = m_pFGraphic->generateImage(pG, pSpanAP, maxW, maxH);
3625 if(m_pImage)
3626 {
3627 iW = pG->tlu(m_pImage->getDisplayWidth());
3628 iH = pG->tlu(m_pImage->getDisplayHeight());
3629 if(iW < maxW)
3630 maxW = iW;
3631 if(iH < maxH)
3632 maxH = iH;
3633 }
3634 const char * pProps[5] = {"width",NULL,"height",NULL,NULL};
3635 m_sCachedWidthProp = UT_formatDimensionString(DIM_IN,static_cast<double>(maxW)/UT_LAYOUT_RESOLUTION);
3636 m_sCachedHeightProp =UT_formatDimensionString(DIM_IN,static_cast<double>(maxH)/UT_LAYOUT_RESOLUTION);
3637 pProps[1] = m_sCachedWidthProp.c_str();
3638 pProps[3] = m_sCachedHeightProp.c_str();
3639 if(!pG->queryProperties(GR_Graphics::DGP_PAPER))
3640 {
3641 //
3642 // Change the properties in the document
3643 //
3644 getBlock()->getDocument()->changeObjectFormatNoUpdate(PTC_AddFmt,m_OH,NULL,pProps);
3645 //
3646 // update the span Attribute/Propperties with this
3647 //
3648 PT_AttrPropIndex api = getBlock()->getDocument()->getAPIFromSOH(m_OH);
3649 getBlock()->getDocument()->getAttrProp(api,&m_pSpanAP);
3650 }
3651 m_bImageForPrinter = pG->queryProperties(GR_Graphics::DGP_PAPER);
3652 markAsDirty();
3653 if(getLine())
3654 {
3655 getLine()->setNeedsRedraw();
3656 }
3657 }
3658 if (m_pImage)
3659 {
3660 _setWidth(pG->tlu(m_pImage->getDisplayWidth()));
3661 _setHeight(pG->tlu(m_pImage->getDisplayHeight()));
3662 }
3663 else
3664 {
3665 // If we have no image, we simply insert a square "slug"
3666
3667 _setWidth(UT_convertToLogicalUnits("0.5in"));
3668 _setHeight(UT_convertToLogicalUnits("0.5in"));
3669 }
3670
3671 // these asserts are no longer valid -- image can be hidden due to
3672 //hidden text mark up or revisions
3673 //UT_ASSERT(getWidth() > 0);
3674 //UT_ASSERT(getHeight() > 0);
3675 m_iImageWidth = getWidth();
3676 m_iImageHeight = getHeight();
3677
3678 _setAscent(_getHeight());
3679 _setDescent(0);
3680 const PP_AttrProp * pBlockAP = NULL;
3681 const PP_AttrProp * pSectionAP = NULL;
3682
3683 getBlockAP(pBlockAP);
3684
3685 FL_DocLayout * pLayout = getBlock()->getDocLayout();
3686 const GR_Font * pFont = pLayout->findFont(pSpanAP,pBlockAP,pSectionAP,getGraphics());
3687
3688 if (pFont != _getFont())
3689 {
3690 _setFont(pFont);
3691 }
3692 m_iPointHeight = pG->getFontAscent(pFont) + getGraphics()->getFontDescent(pFont);
3693 }
3694
canBreakAfter(void) const3695 bool fp_ImageRun::canBreakAfter(void) const
3696 {
3697 return true;
3698 }
3699
canBreakBefore(void) const3700 bool fp_ImageRun::canBreakBefore(void) const
3701 {
3702 return true;
3703 }
3704
_letPointPass(void) const3705 bool fp_ImageRun::_letPointPass(void) const
3706 {
3707 return false;
3708 }
3709
hasLayoutProperties(void) const3710 bool fp_ImageRun::hasLayoutProperties(void) const
3711 {
3712 return true;
3713 }
3714
mapXYToPosition(UT_sint32 x,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)3715 void fp_ImageRun::mapXYToPosition(UT_sint32 x, UT_sint32 /*y*/, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool& /*isTOC*/)
3716 {
3717 //TODO: This one needs fixing for multipage. Get text working first.
3718 //TODO: Find everything that calls this and modify them to allow y-axis.
3719 if (x > getWidth())
3720 pos = getBlock()->getPosition() + getBlockOffset() + getLength();
3721 else
3722 pos = getBlock()->getPosition() + getBlockOffset();
3723
3724 bBOL = false;
3725 bEOL = false;
3726 }
3727
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)3728 void fp_ImageRun::findPointCoords(UT_uint32 iOffset, UT_sint32& x, UT_sint32& y, UT_sint32& x2, UT_sint32& y2, UT_sint32& height, bool& bDirection)
3729 {
3730 //UT_DEBUGMSG(("fintPointCoords: ImmageRun\n"));
3731 UT_sint32 xoff;
3732 UT_sint32 yoff;
3733
3734 UT_ASSERT(getLine());
3735
3736 getLine()->getOffsets(this, xoff, yoff);
3737 if (iOffset == (getBlockOffset() + getLength()))
3738 {
3739 x = xoff + getWidth();
3740 x2 = x;
3741 }
3742 else
3743 {
3744 x = xoff;
3745 x2 = x;
3746 }
3747 y = yoff + getHeight() - m_iPointHeight;
3748 height = m_iPointHeight;
3749 y2 = y;
3750 bDirection = (getVisDirection() != UT_BIDI_LTR);
3751 }
3752
_clearScreen(bool)3753 void fp_ImageRun::_clearScreen(bool /*bFullLineHeightRect*/ )
3754 {
3755 // UT_ASSERT(!isDirty());
3756
3757 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
3758
3759 UT_sint32 xoff = 0, yoff = 0;
3760
3761 // need to clear full height of line, in case we had a selection
3762 getLine()->getScreenOffsets(this, xoff, yoff);
3763 UT_sint32 iLineHeight = getLine()->getHeight();
3764 Fill(getGraphics(),xoff, yoff, getWidth(), iLineHeight);
3765 markAsDirty();
3766 setCleared();
3767 }
3768
getDataId(void) const3769 const char * fp_ImageRun::getDataId(void) const
3770 {
3771 return m_pFGraphic->getDataId();
3772 }
3773
_draw(dg_DrawArgs * pDA)3774 void fp_ImageRun::_draw(dg_DrawArgs* pDA)
3775 {
3776 GR_Graphics *pG = pDA->pG;
3777 if(getBlock()->getDocLayout()->getGraphicTick() != m_iGraphicTick)
3778 {
3779 regenerateImage(pG);
3780 }
3781 else if(!pG->queryProperties(GR_Graphics::DGP_SCREEN))
3782 {
3783 regenerateImage(pG);
3784 m_iGraphicTick = getBlock()->getDocLayout()->getGraphicTick()+999;
3785 }
3786 UT_sint32 xoff = 0, yoff = 0;
3787
3788 if(pG->queryProperties(GR_Graphics::DGP_SCREEN))
3789 {
3790 getLine()->getScreenOffsets(this, xoff, yoff);
3791 }
3792 else
3793 {
3794 getLine()->getOffsets(this, xoff, yoff);
3795 if(_getView()->getViewMode() != VIEW_PRINT)
3796 {
3797 yoff += static_cast<fl_DocSectionLayout *>(getBlock()->getDocSectionLayout())->getTopMargin();
3798 }
3799 }
3800
3801 yoff += getLine()->getAscent() - getAscent() + 1;
3802 // clip drawing to the page
3803 UT_Rect pClipRect;
3804 pClipRect.top = yoff;
3805 pClipRect.left = xoff;
3806 pClipRect.height = getLine()->getContainer()->getHeight();
3807 pClipRect.width = getLine()->getContainer()->getWidth();
3808 pClipRect.height -= getLine()->getY();
3809 //
3810 // SEVIOR Says don't touch this if statement unless you know how to make windows
3811 // and gnome-print print images. Otherwise your commit priviliges will be revoked.
3812 //
3813 // Try me. -- Hub
3814 std::unique_ptr<UT_Rect> pSavedRect;
3815 if(pG->getClipRect())
3816 {
3817 pSavedRect.reset(new UT_Rect(pG->getClipRect()));
3818 }
3819 if(pG->queryProperties(GR_Graphics::DGP_SCREEN))
3820 {
3821 //
3822 // Take the interesction of the applied rectangle;
3823 if(pSavedRect)
3824 {
3825 UT_sint32 iTop,iLeft,iWidth,iHeight;
3826 iTop = 0;
3827 iLeft = 0;
3828 iWidth = 0;
3829 iHeight = 0;
3830 iTop = pClipRect.top;
3831 if(pSavedRect->top > pClipRect.top)
3832 {
3833 iTop = pSavedRect->top;
3834 }
3835 UT_sint32 iBot = pClipRect.top + pClipRect.height;
3836 if((pSavedRect->top + pSavedRect->height) < (pClipRect.top + pClipRect.height))
3837 {
3838 iBot = pSavedRect->top + pSavedRect->height;
3839 }
3840 iHeight = iBot - iTop;
3841 if(iHeight < pG->tlu(1))
3842 {
3843 iHeight = pG->tlu(2);
3844 }
3845 iLeft = pClipRect.left;
3846 if(pSavedRect->left > pClipRect.left)
3847 {
3848 iLeft = pSavedRect->left;
3849 }
3850 UT_sint32 iRight = pClipRect.left + pClipRect.width;
3851 if((pSavedRect->left + pSavedRect->width) < (pClipRect.left + pClipRect.width))
3852 {
3853 iRight = pSavedRect->left + pSavedRect->width;
3854 }
3855 iWidth = iRight - iLeft;
3856 if(iWidth < pG->tlu(1))
3857 {
3858 iWidth = pG->tlu(2);
3859 }
3860 pClipRect.left = iLeft;
3861 pClipRect.width = iWidth;
3862 pClipRect.top = iTop;
3863 pClipRect.height = iHeight;
3864 pG->setClipRect(&pClipRect);
3865 }
3866 }
3867
3868 FV_View* pView = _getView();
3869
3870 GR_Painter painter(pG);
3871
3872 if (m_pImage)
3873 {
3874 // Paint the background if there is alpha in the image
3875 if(pG->queryProperties(GR_Graphics::DGP_SCREEN) && m_pImage->hasAlpha())
3876 {
3877 Fill(pG,xoff,yoff,getWidth(),getHeight());
3878 }
3879 // draw the image (always)
3880 painter.drawImage(m_pImage, xoff, yoff);
3881
3882 // if we're the selection, draw some pretty selection markers
3883 if (pG->queryProperties(GR_Graphics::DGP_SCREEN))
3884 {
3885 UT_uint32 iRunBase = getBlock()->getPosition() + getBlockOffset();
3886
3887 UT_uint32 iSelAnchor = pView->getSelectionAnchor();
3888 UT_uint32 iPoint = pView->getPoint();
3889
3890 UT_uint32 iSel1 = UT_MIN(iSelAnchor, iPoint);
3891 UT_uint32 iSel2 = UT_MAX(iSelAnchor, iPoint);
3892
3893 UT_ASSERT(iSel1 <= iSel2);
3894
3895 if (
3896 /* pView->getFocus()!=AV_FOCUS_NONE && */
3897 (iSel1 <= iRunBase)
3898 && (iSel2 > iRunBase)
3899 )
3900 {
3901 UT_uint32 top = yoff;
3902 UT_uint32 left = xoff;
3903 UT_uint32 right = xoff + getWidth() - pG->tlu(1);
3904 UT_uint32 bottom = yoff + getHeight() - pG->tlu(1);
3905
3906 UT_Rect box(left, top, right - left, bottom - top);
3907 pView->drawSelectionBox(box, true);
3908 }
3909 }
3910
3911 }
3912 else
3913 {
3914 painter.fillRect(pView->getColorImage(), xoff, yoff, getWidth(), getHeight());
3915 }
3916
3917 // unf*ck clipping rect
3918 pG->setClipRect(pSavedRect.get());
3919 }
3920
getImage()3921 GR_Image * fp_ImageRun::getImage()
3922 {
3923 return m_pImage;
3924 }
3925
3926 //////////////////////////////////////////////////////////////////
3927 //////////////////////////////////////////////////////////////////
3928
3929 #define _FIELD(type,desc,tag) /*nothing*/
3930 #define _FIELDTYPE(type,desc) {FPFIELDTYPE_##type, NULL, desc},
3931
3932 fp_FieldTypeData fp_FieldTypes[] = {
3933
3934 #include "fp_Fields.h"
3935
3936 {FPFIELDTYPE_END, NULL, 0} };
3937
3938 #undef _FIELD
3939 #undef _FIELDTYPE
3940
3941 // The way to turn macro argument into string constant
3942 #define xstr2(x) #x
3943 #define xstr(x) xstr2(x)
3944 #define _FIELD(type,desc,tag) {FPFIELDTYPE_##type, FPFIELD_##tag, NULL, xstr(tag), desc},
3945 #define _FIELDTYPE(type,desc) /*nothing*/
3946
3947 fp_FieldData fp_FieldFmts[] = {
3948
3949 #include "fp_Fields.h"
3950
3951 {FPFIELDTYPE_END, FPFIELD_end, NULL, NULL, 0} };
3952
3953 #undef xstr2
3954 #undef xstr
3955 #undef _FIELD
3956 #undef _FIELDTYPE
3957
fp_FieldRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)3958 fp_FieldRun::fp_FieldRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen)
3959 : fp_Run(pBL, iOffsetFirst, iLen, FPRUN_FIELD),
3960 m_iFieldType(FPFIELD_start),
3961 m_pParameter(0),
3962 m_fPosition(TEXT_POSITION_NORMAL)
3963 {
3964 fd_Field * fd;
3965 lookupProperties();
3966 if(!getBlock()->isContainedByTOC())
3967 {
3968 bool gotField = pBL->getField(iOffsetFirst,fd);
3969 if(gotField)
3970 {
3971 _setField(fd);
3972 }
3973 }
3974 // UT_ASSERT(gotField);
3975 m_sFieldValue[0] = 0;
3976 }
3977
~fp_FieldRun(void)3978 fp_FieldRun::~fp_FieldRun(void)
3979 {
3980 xxx_UT_DEBUGMSG(("FieldRun deleted %x FieldType %d \n",this,getFieldType()));
3981 return;
3982 }
3983
_recalcWidth()3984 bool fp_FieldRun::_recalcWidth()
3985 {
3986 // TODO -- is this really needed ???
3987 // this should not be needed, since lookup properties is called
3988 // when formatting changes - Tomas
3989 //lookupProperties();
3990
3991 getGraphics()->setFont(_getFont());
3992 UT_sint32 iNewWidth = 0;
3993 if(UT_UCS4_strlen(m_sFieldValue) > 0)
3994 {
3995 iNewWidth = getGraphics()->measureString(m_sFieldValue,
3996 0,
3997 UT_UCS4_strlen(m_sFieldValue),
3998 NULL);
3999 }
4000 if (iNewWidth != getWidth())
4001 {
4002 clearScreen();
4003 markAsDirty();
4004 if(getLine())
4005 {
4006 getLine()->setNeedsRedraw();
4007 }
4008 if(getBlock())
4009 {
4010 getBlock()->setNeedsRedraw();
4011 }
4012 _setWidth(iNewWidth);
4013
4014 return true;
4015 }
4016
4017 return false;
4018 }
4019
_setValue(const UT_UCSChar * p_new_value)4020 bool fp_FieldRun::_setValue(const UT_UCSChar *p_new_value)
4021 {
4022 if (0 != UT_UCS4_strcmp(p_new_value, m_sFieldValue))
4023 {
4024 xxx_UT_DEBUGMSG(("fp_FieldRun::_setValue: setting new value\n"));
4025 clearScreen();
4026 markAsDirty();
4027 if(getLine())
4028 {
4029 getLine()->setNeedsRedraw();
4030 }
4031 if(getBlock())
4032 {
4033 getBlock()->setNeedsRedraw();
4034 }
4035
4036 markDrawBufferDirty();
4037 UT_uint32 iLen = UT_UCS4_strlen(p_new_value);
4038 iLen = UT_MIN(iLen,FPFIELD_MAX_LENGTH);
4039
4040 if(iLen > 1 && XAP_App::getApp()->theOSHasBidiSupport() == XAP_App::BIDI_SUPPORT_GUI)
4041 {
4042 UT_BidiCharType prevType, myType;
4043
4044 if(getPrevRun())
4045 prevType = getPrevRun()->getVisDirection();
4046 else
4047 prevType = getBlock()->getDominantDirection();
4048
4049 myType = prevType;
4050 UT_bidiReorderString(p_new_value, iLen, myType, m_sFieldValue);
4051
4052 m_sFieldValue[iLen] = 0;
4053 }
4054 else
4055 {
4056 UT_UCS4_strcpy(m_sFieldValue, p_new_value);
4057 }
4058
4059 {
4060 // TODO -- is this really needed???
4061 // should not be, since lookupProperties is called on
4062 // formatting changes - Tomas
4063 // lookupProperties();
4064
4065 getGraphics()->setFont(_getFont());
4066
4067 UT_sint32 iNewWidth =
4068 getGraphics()->measureString(m_sFieldValue,
4069 0,
4070 UT_UCS4_strlen(m_sFieldValue),
4071 NULL);
4072 if (iNewWidth != getWidth())
4073 {
4074 _setWidth(iNewWidth);
4075 markWidthDirty();
4076 return true;
4077 }
4078
4079 }
4080 }
4081 xxx_UT_DEBUGMSG(("fp_FieldRun::_setValue: value has not changed [0] %x \n", m_sFieldValue[0]));
4082
4083 return false;
4084 }
4085
_lookupProperties(const PP_AttrProp * pSpanAP,const PP_AttrProp * pBlockAP,const PP_AttrProp * pSectionAP,GR_Graphics * pG)4086 void fp_FieldRun::_lookupProperties(const PP_AttrProp * pSpanAP,
4087 const PP_AttrProp * pBlockAP,
4088 const PP_AttrProp * pSectionAP,
4089 GR_Graphics * pG)
4090 {
4091 if(pG == NULL)
4092 {
4093 pG = getGraphics();
4094 }
4095 PD_Document * pDoc = getBlock()->getDocument();
4096 fd_Field * fd = NULL;
4097 if(!getBlock()->isContainedByTOC())
4098 {
4099 getBlock()->getField(getBlockOffset() /*+1*/,fd); // Next Pos?
4100 _setField(fd);
4101 }
4102 else
4103 {
4104 _setField(NULL);
4105 }
4106 if(getField() != NULL)
4107 {
4108 getField()->setBlock(getBlock());
4109 }
4110 // look for fonts in this DocLayout's font cache
4111 FL_DocLayout * pLayout = getBlock()->getDocLayout();
4112
4113 UT_RGBColor clrFG;
4114 UT_parseColor(PP_evalProperty("color",pSpanAP,pBlockAP,pSectionAP, getBlock()->getDocument(), true), clrFG);
4115 _setColorFG(clrFG);
4116
4117 const char * pszFieldColor = NULL;
4118 pszFieldColor = PP_evalProperty("field-color",pSpanAP,pBlockAP,pSectionAP, getBlock()->getDocument(), true);
4119
4120 const char * pszBGColor = NULL;
4121 pszBGColor = PP_evalProperty("bgcolor",pSpanAP,pBlockAP,pSectionAP, getBlock()->getDocument(), true);
4122
4123 //
4124 // FIXME: The "ffffff" is for backwards compatibility. If we don't exclude this
4125 // no prexisting docs will be able to change the Highlight color in paragraphs
4126 // with lists. I think this is a good solution for now. However it does mean
4127 // field-color of "ffffff", pure white is actually transparent.
4128 //
4129 if(pszFieldColor && strcmp(pszFieldColor,"transparent") != 0 && strcmp(pszFieldColor,"ffffff" ) != 0 && pG->queryProperties(GR_Graphics::DGP_SCREEN))
4130 {
4131 UT_RGBColor r;
4132 UT_parseColor(pszFieldColor, r);
4133 _setColorHL(r);
4134 }
4135 else if (pszBGColor && strcmp(pszFieldColor,"transparent") != 0)
4136 {
4137 UT_RGBColor r;
4138 UT_parseColor(pszBGColor, r);
4139 _setColorHL(r);
4140 }
4141
4142
4143 const gchar* pszType = NULL;
4144 const gchar* pszParam = NULL;
4145
4146 if(pSpanAP)
4147 {
4148 pSpanAP->getAttribute("type", pszType);
4149 pSpanAP->getAttribute("param", pszParam);
4150 }
4151 else
4152 {
4153 pBlockAP->getAttribute("type",pszType);
4154 pBlockAP->getAttribute("param", pszParam);
4155 }
4156
4157 if(pszParam)
4158 m_pParameter = pszParam;
4159
4160 // i leave this in because it might be obscuring a larger bug
4161 //UT_ASSERT(pszType);
4162 if (!pszType) return;
4163
4164 int i;
4165 if(pszType != NULL)
4166 {
4167 for( i = 0; fp_FieldFmts[i].m_Tag != NULL; i++ )
4168 {
4169 if (0 == strcmp(pszType, fp_FieldFmts[i].m_Tag))
4170 {
4171 m_iFieldType = fp_FieldFmts[i].m_Num;
4172 break;
4173 }
4174 }
4175 if( fp_FieldFmts[i].m_Tag == NULL )
4176 {
4177 // probably new type of field
4178 // UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
4179 }
4180 }
4181
4182 xxx_UT_DEBUGMSG(("FieldRun: Lookup Properties field type %d \n",m_iFieldType));
4183 if(m_iFieldType == FPFIELD_list_label)
4184 {
4185 _setFont(pLayout->findFont(pSpanAP,pBlockAP,pSectionAP,pG, true));
4186 }
4187 else
4188 {
4189 _setFont(pLayout->findFont(pSpanAP,pBlockAP,pSectionAP, pG));
4190 }
4191 xxx_UT_DEBUGMSG(("Field font is set to %s \n",_getFont()->getFamily()));
4192 _setAscent(pG->getFontAscent(_getFont()));
4193 _setDescent(pG->getFontDescent(_getFont()));
4194 _setHeight(pG->getFontHeight(_getFont()));
4195
4196 const gchar * pszPosition = PP_evalProperty("text-position",pSpanAP,pBlockAP,pSectionAP, pDoc, true);
4197
4198 if (0 == strcmp(pszPosition, "superscript"))
4199 {
4200 m_fPosition = TEXT_POSITION_SUPERSCRIPT;
4201 }
4202 else if (0 == strcmp(pszPosition, "subscript"))
4203 {
4204 m_fPosition = TEXT_POSITION_SUBSCRIPT;
4205 }
4206 else
4207 {
4208 m_fPosition = TEXT_POSITION_NORMAL;
4209 }
4210 //
4211 // Lookup Decoration properties for this run
4212 //
4213 const gchar *pszDecor = PP_evalProperty("text-decoration",pSpanAP,pBlockAP,pSectionAP, getBlock()->getDocument(), true);
4214 _setLineWidth(getToplineThickness());
4215 _setDecorations(0);
4216 gchar* p;
4217 if (!(p = g_strdup(pszDecor)))
4218 {
4219 // TODO outofmem
4220 }
4221 UT_ASSERT(p || !pszDecor);
4222 gchar* q = strtok(p, " ");
4223
4224 while (q)
4225 {
4226 if (0 == strcmp(q, "underline"))
4227 {
4228 _orDecorations(TEXT_DECOR_UNDERLINE);
4229 }
4230 else if (0 == strcmp(q, "overline"))
4231 {
4232 _orDecorations(TEXT_DECOR_OVERLINE);
4233 }
4234 else if (0 == strcmp(q, "line-through"))
4235 {
4236 _orDecorations(TEXT_DECOR_LINETHROUGH);
4237 }
4238 else if (0 == strcmp(q, "topline"))
4239 {
4240 _orDecorations(TEXT_DECOR_TOPLINE);
4241 }
4242 else if (0 == strcmp(q, "bottomline"))
4243 {
4244 _orDecorations(TEXT_DECOR_BOTTOMLINE);
4245 }
4246 q = strtok(NULL, " ");
4247 }
4248
4249 g_free(p);
4250 }
4251
4252
getFieldType(void) const4253 fp_FieldsEnum fp_FieldRun::getFieldType(void) const
4254 {
4255 return m_iFieldType;
4256 }
4257
canBreakAfter(void) const4258 bool fp_FieldRun::canBreakAfter(void) const
4259 {
4260 return true;
4261 }
4262
canBreakBefore(void) const4263 bool fp_FieldRun::canBreakBefore(void) const
4264 {
4265 return true;
4266 }
4267
_letPointPass(void) const4268 bool fp_FieldRun::_letPointPass(void) const
4269 {
4270 return true;
4271 }
4272
isSuperscript(void) const4273 bool fp_FieldRun::isSuperscript(void) const
4274 {
4275 return (m_fPosition == TEXT_POSITION_SUPERSCRIPT);
4276 }
4277
isSubscript(void) const4278 bool fp_FieldRun::isSubscript(void) const
4279 {
4280 return (m_fPosition == TEXT_POSITION_SUBSCRIPT);
4281 }
4282
hasLayoutProperties(void) const4283 bool fp_FieldRun::hasLayoutProperties(void) const
4284 {
4285 return true;
4286 }
4287
mapXYToPosition(UT_sint32 x,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)4288 void fp_FieldRun::mapXYToPosition(UT_sint32 x, UT_sint32 /*y*/, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool& /*isTOC*/)
4289 {
4290 //TODO: Find everything that calls this and modify them to allow y-axis.
4291
4292 // If X is left of the middle, return offset to the left,
4293 // otherwise the offset to the right.
4294 if (x < (getWidth() / 2))
4295 pos = getBlock()->getPosition() + getBlockOffset();
4296 else
4297 pos = getBlock()->getPosition() + getBlockOffset() + getLength();
4298
4299 bBOL = false;
4300 if(getNextRun() == NULL)
4301 {
4302 bEOL = true;
4303 }
4304 if(getNextRun()->getType() == FPRUN_ENDOFPARAGRAPH)
4305 {
4306 bEOL = true;
4307 }
4308 }
4309
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)4310 void fp_FieldRun::findPointCoords(UT_uint32 iOffset, UT_sint32& x,
4311 UT_sint32& y, UT_sint32& x2,
4312 UT_sint32& y2, UT_sint32& height, bool& bDirection)
4313 {
4314 xxx_UT_DEBUGMSG(("findPointCoords: FieldRun offset %d \n",iOffset));
4315 UT_sint32 xoff;
4316 UT_sint32 yoff;
4317
4318 UT_ASSERT(getLine());
4319
4320 // TODO is this really needed ???
4321 // should not be, since lookupProperties is called on
4322 // formatting changes - Tomas
4323 // lookupProperties();
4324
4325 getLine()->getOffsets(this, xoff, yoff);
4326 xxx_UT_DEBUGMSG(("findPointCoords: FieldRun orig yoff %d \n",yoff));
4327 //
4328 // The footnote code is to handle discontinuities in offset from embedded
4329 // footnotes in blocks.
4330 //
4331 bool bFootnote = false;
4332 if (iOffset == (getBlockOffset() + getLength()))
4333 {
4334 xoff += getWidth();
4335 }
4336 else if(iOffset > (getBlockOffset() + getLength()))
4337 {
4338 bFootnote = true;
4339 xoff += getWidth();
4340 }
4341
4342 if (!bFootnote && (m_fPosition == TEXT_POSITION_SUPERSCRIPT))
4343 {
4344 yoff -= getAscent() * 1/2;
4345 }
4346 else if (!bFootnote && (m_fPosition == TEXT_POSITION_SUBSCRIPT))
4347 {
4348 yoff += getDescent() /* * 3/2 */;
4349 }
4350 xxx_UT_DEBUGMSG(("findPointCoords: FieldRun yoff %d \n",yoff));
4351 x = xoff;
4352 y = yoff;
4353 if(!bFootnote)
4354 {
4355 height = getHeight();
4356 }
4357 else
4358 {
4359 //
4360 // We're actually just before the next run and in the insertion point will be
4361 // in the next run so make the insertion point reflect this.
4362 //
4363 if(getNextRun() && getNextRun()->hasLayoutProperties() )
4364 {
4365 height = getNextRun()->getHeight();
4366 UT_sint32 xx,xx2,yy2,hheight;
4367 bool bbDirection;
4368 getNextRun()->findPointCoords(iOffset+1,xx,y,xx2,yy2, hheight,
4369 bbDirection);
4370 height = hheight;
4371
4372 }
4373 else
4374 {
4375 height = getHeight();
4376 }
4377 }
4378 x2 = x;
4379 y2 = y;
4380 bDirection = (getVisDirection() != UT_BIDI_LTR);
4381 }
4382
calculateValue(void)4383 bool fp_FieldRun::calculateValue(void)
4384 {
4385 //
4386 // Code for the Piece Table Fields Calculation
4387 // Get size of the field from the following runs
4388 //
4389 // return getField()->update();
4390 // UT_ASSERT(getField());
4391
4392 /* UT_sint32 count = 0;
4393 fp_Run* pNext = getNextRun();
4394 while(pNext != NULL && pNext->getField() != NULL )
4395 {
4396 if(getField() == NULL)
4397 {
4398 getField() = pNext->getField();
4399 }
4400 pNext = getNextRun();
4401 count++;
4402 }
4403 if(count == 0)
4404 {
4405 setWidth(0);
4406 _setHeight(0);
4407 }
4408 else
4409 {
4410 pNext = getPrevRun();
4411 setWidth(pNext->getWidth());
4412 _setHeight(pNext->getHeight());
4413 }
4414 if(getField() != NULL)
4415 getField()->update();
4416 */
4417 return true;
4418 }
4419
_clearScreen(bool)4420 void fp_FieldRun::_clearScreen(bool /* bFullLineHeightRect */)
4421 {
4422 // UT_ASSERT(!isDirty());
4423
4424 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
4425 UT_sint32 xoff = 0, yoff = 0;
4426
4427 // need to clear full height of line, in case we had a selection
4428 getLine()->getScreenOffsets(this, xoff, yoff);
4429 UT_sint32 iLineHeight = getLine()->getHeight();
4430 Fill(getGraphics(), xoff, yoff, getWidth(), iLineHeight);
4431 }
4432
_defaultDraw(dg_DrawArgs * pDA)4433 void fp_FieldRun::_defaultDraw(dg_DrawArgs* pDA)
4434 {
4435 GR_Graphics * pG = pDA->pG;
4436
4437 // TODO is this really needed
4438 // should not be, since lookupProperties is called on
4439 // formatting changes - Tomas
4440 // lookupProperties();
4441 UT_sint32 xoff = 0, yoff = 0;
4442
4443 GR_Painter painter(pG);
4444
4445 // need screen locations of this run
4446
4447 getLine()->getScreenOffsets(this, xoff, yoff);
4448
4449 UT_sint32 iYdraw = pDA->yoff - getAscent()-1;
4450
4451 if (m_fPosition == TEXT_POSITION_SUPERSCRIPT)
4452 {
4453 iYdraw -= getAscent() * 1/2;
4454 }
4455 else if (m_fPosition == TEXT_POSITION_SUBSCRIPT)
4456 {
4457 iYdraw += getDescent(); // * 3/2
4458 }
4459
4460 //if (pG->queryProperties(GR_Graphics::DGP_SCREEN))
4461 {
4462 UT_uint32 iRunBase = getBlock()->getPosition() + getBlockOffset();
4463
4464 //
4465 // Sevior was here
4466 // UT_sint32 iFillTop = iYdraw;
4467 UT_sint32 iFillTop = iYdraw+1;
4468 UT_sint32 iFillHeight = getAscent() + getDescent();
4469
4470 FV_View* pView = _getView();
4471 UT_uint32 iSelAnchor = pView->getSelectionAnchor();
4472 UT_uint32 iPoint = pView->getPoint();
4473
4474 UT_uint32 iSel1 = UT_MIN(iSelAnchor, iPoint);
4475 UT_uint32 iSel2 = UT_MAX(iSelAnchor, iPoint);
4476
4477 UT_ASSERT(iSel1 <= iSel2);
4478 bool bIsInTOC = getBlock()->isContainedByTOC();
4479 if (
4480 isInSelectedTOC() || (!bIsInTOC && (
4481 /* pView->getFocus()!=AV_FOCUS_NONE && */
4482 (iSel1 <= iRunBase)
4483 && (iSel2 > iRunBase)))
4484 )
4485 {
4486 UT_RGBColor color(_getView()->getColorSelBackground());
4487 pG->setColor(_getView()->getColorSelForeground());
4488 painter.fillRect(color, pDA->xoff, iFillTop, getWidth(), iFillHeight);
4489
4490 }
4491 else
4492 {
4493 if (m_iFieldType != FPFIELD_list_label)
4494 Fill(getGraphics(),pDA->xoff, iFillTop, getWidth(), iFillHeight);
4495 pG->setColor(_getColorFG());
4496 }
4497 }
4498
4499 pG->setFont(_getFont());
4500 xxx_UT_DEBUGMSG(("Field draw with font %s \n",_getFont()->getFamily()));
4501
4502 UT_uint32 len = UT_UCS4_strlen(m_sFieldValue);
4503 if (len == 0)
4504 {
4505 return;
4506 }
4507
4508 painter.drawChars(m_sFieldValue, 0, len, pDA->xoff,iYdraw, NULL);
4509 //
4510 // Draw underline/overline/strikethough
4511 //
4512 UT_sint32 yTopOfRun = pDA->yoff - getAscent()-1; // Hack to remove
4513 //character dirt
4514 xxx_UT_DEBUGMSG(("xoff infield before drawdecors %d \n",pDA->xoff));
4515 drawDecors( pDA->xoff, yTopOfRun,pG);
4516
4517 }
4518
4519 // BEGIN DOM work on some new fields
4520
fp_FieldCharCountRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4521 fp_FieldCharCountRun::fp_FieldCharCountRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4522 {
4523 }
4524
calculateValue(void)4525 bool fp_FieldCharCountRun::calculateValue(void)
4526 {
4527 UT_UTF8String szFieldValue;
4528
4529 FV_View *pView = _getView();
4530 if(!pView)
4531 {
4532 szFieldValue ="?";
4533 }
4534 else
4535 {
4536 FV_DocCount cnt = pView->countWords(true);
4537 UT_UTF8String_sprintf(szFieldValue, "%d", cnt.ch_sp);
4538 }
4539 if (getField())
4540 getField()->setValue(static_cast<const gchar*>(szFieldValue.utf8_str()));
4541
4542 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4543 }
4544
fp_FieldNonBlankCharCountRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4545 fp_FieldNonBlankCharCountRun::fp_FieldNonBlankCharCountRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4546 {
4547 }
4548
calculateValue(void)4549 bool fp_FieldNonBlankCharCountRun::calculateValue(void)
4550 {
4551 UT_UTF8String szFieldValue ("?");
4552
4553 FV_View *pView = _getView();
4554 if(pView)
4555 {
4556 FV_DocCount cnt = pView->countWords(true);
4557 UT_UTF8String_sprintf(szFieldValue, "%d", cnt.ch_no);
4558 }
4559
4560 if (getField())
4561 getField()->setValue(static_cast<const gchar*>(szFieldValue.utf8_str()));
4562
4563 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4564 }
4565
fp_FieldLineCountRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4566 fp_FieldLineCountRun::fp_FieldLineCountRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4567 {
4568 }
4569
calculateValue(void)4570 bool fp_FieldLineCountRun::calculateValue(void)
4571 {
4572 FV_View *pView = _getView();
4573 UT_UTF8String szFieldValue ("?");
4574
4575 if(pView)
4576 {
4577 FV_DocCount cnt = pView->countWords(false);
4578 UT_UTF8String_sprintf(szFieldValue, "%d", cnt.line);
4579 }
4580
4581 if (getField())
4582 getField()->setValue(static_cast<const gchar*>(szFieldValue.utf8_str()));
4583
4584 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4585 }
4586
fp_FieldParaCountRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4587 fp_FieldParaCountRun::fp_FieldParaCountRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4588 {
4589 }
4590
4591
calculateValue(void)4592 bool fp_FieldParaCountRun::calculateValue(void)
4593 {
4594 FV_View *pView = _getView();
4595 UT_UTF8String szFieldValue ("?");
4596 if(pView)
4597 {
4598 FV_DocCount cnt = pView->countWords(false);
4599 UT_UTF8String_sprintf(szFieldValue, "%d", cnt.para);
4600 }
4601
4602 if (getField())
4603 getField()->setValue(static_cast<const gchar*>(szFieldValue.utf8_str()));
4604
4605 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4606 }
4607
fp_FieldWordCountRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4608 fp_FieldWordCountRun::fp_FieldWordCountRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4609 {
4610 }
4611
calculateValue(void)4612 bool fp_FieldWordCountRun::calculateValue(void)
4613 {
4614 FV_View *pView = _getView();
4615 UT_UTF8String szFieldValue ("?");
4616 if(pView)
4617 {
4618 FV_DocCount cnt = pView->countWords(true);
4619 UT_UTF8String_sprintf(szFieldValue, "%d", cnt.word);
4620 }
4621
4622 if (getField())
4623 getField()->setValue(static_cast<const gchar*>(szFieldValue.utf8_str()));
4624
4625 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4626 }
4627
4628 // mm/dd/yy notation
fp_FieldMMDDYYRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4629 fp_FieldMMDDYYRun::fp_FieldMMDDYYRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4630 {
4631 }
4632
calculateValue(void)4633 bool fp_FieldMMDDYYRun::calculateValue(void)
4634 {
4635 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4636 sz_ucs_FieldValue[0] = 0;
4637
4638 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4639
4640 time_t tim = time(NULL);
4641 struct tm *pTime = localtime(&tim);
4642
4643 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%m/%d/%y", pTime);
4644 if (getField())
4645 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4646
4647 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4648
4649 return _setValue(sz_ucs_FieldValue);
4650 }
4651
4652 // dd/mm/yy time
fp_FieldDDMMYYRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4653 fp_FieldDDMMYYRun::fp_FieldDDMMYYRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4654 {
4655 }
4656
calculateValue(void)4657 bool fp_FieldDDMMYYRun::calculateValue(void)
4658 {
4659 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4660 sz_ucs_FieldValue[0] = 0;
4661
4662 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4663
4664 time_t tim = time(NULL);
4665 struct tm *pTime = localtime(&tim);
4666
4667 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%d/%m/%y", pTime);
4668 if (getField())
4669 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4670
4671 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4672
4673 return _setValue(sz_ucs_FieldValue);
4674 }
4675
4676 // Month Day, Year
fp_FieldMonthDayYearRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4677 fp_FieldMonthDayYearRun::fp_FieldMonthDayYearRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4678 {
4679 }
4680
calculateValue(void)4681 bool fp_FieldMonthDayYearRun::calculateValue(void)
4682 {
4683 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4684 sz_ucs_FieldValue[0] = 0;
4685
4686 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4687
4688 time_t tim = time(NULL);
4689 struct tm *pTime = localtime(&tim);
4690
4691 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%B %d, %Y", pTime);
4692 if (getField())
4693 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4694
4695 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4696
4697 return _setValue(sz_ucs_FieldValue);
4698 }
4699
fp_FieldMthDayYearRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4700 fp_FieldMthDayYearRun::fp_FieldMthDayYearRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4701 {
4702 }
4703
calculateValue(void)4704 bool fp_FieldMthDayYearRun::calculateValue(void)
4705 {
4706 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4707 sz_ucs_FieldValue[0] = 0;
4708
4709 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4710
4711 time_t tim = time(NULL);
4712 struct tm *pTime = localtime(&tim);
4713
4714 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%b %d, %Y", pTime);
4715 if (getField())
4716 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4717
4718 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4719
4720 return _setValue(sz_ucs_FieldValue);
4721 }
4722
fp_FieldDefaultDateRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4723 fp_FieldDefaultDateRun::fp_FieldDefaultDateRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4724 {
4725 }
4726
calculateValue(void)4727 bool fp_FieldDefaultDateRun::calculateValue(void)
4728 {
4729 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4730 sz_ucs_FieldValue[0] = 0;
4731
4732 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4733
4734 time_t tim = time(NULL);
4735 struct tm *pTime = localtime(&tim);
4736
4737 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%c", pTime);
4738 if (getField())
4739 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4740
4741 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4742
4743 return _setValue(sz_ucs_FieldValue);
4744 }
4745
fp_FieldDefaultDateNoTimeRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4746 fp_FieldDefaultDateNoTimeRun::fp_FieldDefaultDateNoTimeRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4747 {
4748 }
4749
calculateValue(void)4750 bool fp_FieldDefaultDateNoTimeRun::calculateValue(void)
4751 {
4752 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4753 sz_ucs_FieldValue[0] = 0;
4754
4755 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4756
4757 time_t tim = time(NULL);
4758 struct tm *pTime = localtime(&tim);
4759
4760 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%x", pTime);
4761 if (getField())
4762 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4763
4764 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4765
4766 return _setValue(sz_ucs_FieldValue);
4767 }
4768
fp_FieldWkdayRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4769 fp_FieldWkdayRun::fp_FieldWkdayRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4770 {
4771 }
4772
calculateValue(void)4773 bool fp_FieldWkdayRun::calculateValue(void)
4774 {
4775 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4776 sz_ucs_FieldValue[0] = 0;
4777
4778 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4779
4780 time_t tim = time(NULL);
4781 struct tm *pTime = localtime(&tim);
4782
4783 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%A", pTime);
4784 if (getField())
4785 getField()->setValue(static_cast<const gchar*>(g_strdup(szFieldValue)));
4786
4787 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4788
4789 return _setValue(sz_ucs_FieldValue);
4790 }
4791
fp_FieldDOYRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4792 fp_FieldDOYRun::fp_FieldDOYRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4793 {
4794 }
4795
calculateValue(void)4796 bool fp_FieldDOYRun::calculateValue(void)
4797 {
4798 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4799 sz_ucs_FieldValue[0] = 0;
4800
4801 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4802
4803 time_t tim = time(NULL);
4804 struct tm *pTime = localtime(&tim);
4805
4806 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%j", pTime);
4807 if (getField())
4808 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4809
4810 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4811
4812 return _setValue(sz_ucs_FieldValue);
4813 }
4814
fp_FieldMilTimeRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4815 fp_FieldMilTimeRun::fp_FieldMilTimeRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4816 {
4817 }
4818
calculateValue(void)4819 bool fp_FieldMilTimeRun::calculateValue(void)
4820 {
4821 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4822 sz_ucs_FieldValue[0] = 0;
4823
4824 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4825
4826 time_t tim = time(NULL);
4827 struct tm *pTime = localtime(&tim);
4828
4829 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%H:%M:%S", pTime);
4830 if (getField())
4831 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4832
4833 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4834
4835 return _setValue(sz_ucs_FieldValue);
4836 }
4837
fp_FieldAMPMRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4838 fp_FieldAMPMRun::fp_FieldAMPMRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4839 {
4840 }
4841
calculateValue(void)4842 bool fp_FieldAMPMRun::calculateValue(void)
4843 {
4844 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4845 sz_ucs_FieldValue[0] = 0;
4846
4847 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4848
4849 time_t tim = time(NULL);
4850 struct tm *pTime = localtime(&tim);
4851
4852 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%p", pTime);
4853 if (getField())
4854 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4855
4856 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4857
4858 return _setValue(sz_ucs_FieldValue);
4859 }
4860
fp_FieldTimeEpochRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4861 fp_FieldTimeEpochRun::fp_FieldTimeEpochRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4862 {
4863 }
4864
calculateValue(void)4865 bool fp_FieldTimeEpochRun::calculateValue(void)
4866 {
4867 UT_UTF8String szFieldValue;
4868
4869 time_t tim = time(NULL);
4870 UT_UTF8String_sprintf(szFieldValue, "%ld", static_cast<long>(tim));
4871 if (getField())
4872 getField()->setValue(static_cast<const gchar*>(szFieldValue.utf8_str()));
4873
4874 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4875 }
4876
fp_FieldDateTimeCustomRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4877 fp_FieldDateTimeCustomRun::fp_FieldDateTimeCustomRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4878 {
4879 }
4880
calculateValue(void)4881 bool fp_FieldDateTimeCustomRun::calculateValue(void)
4882 {
4883 fd_Field * fld = getField();
4884 if (fld) {
4885 const gchar * param = fld->getParameter ();
4886
4887 if (!param) // sensible fallback if no param specified
4888 param = "%x %X";
4889
4890 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4891 sz_ucs_FieldValue[0] = 0;
4892
4893 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4894
4895 time_t tim = time(NULL);
4896 struct tm *pTime = localtime(&tim);
4897
4898 strftime(szFieldValue, FPFIELD_MAX_LENGTH, param, pTime);
4899 if (getField())
4900 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4901
4902 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4903
4904 return _setValue(sz_ucs_FieldValue);
4905 }
4906
4907 return false;
4908 }
4909
fp_FieldTimeZoneRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4910 fp_FieldTimeZoneRun::fp_FieldTimeZoneRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4911 {
4912 }
4913
calculateValue(void)4914 bool fp_FieldTimeZoneRun::calculateValue(void)
4915 {
4916 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
4917 sz_ucs_FieldValue[0] = 0;
4918
4919 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
4920
4921 time_t tim = time(NULL);
4922 struct tm *pTime = localtime(&tim);
4923
4924 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%Z", pTime);
4925 if (getField())
4926 getField()->setValue(static_cast<const gchar*>(szFieldValue));
4927
4928 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
4929
4930 return _setValue(sz_ucs_FieldValue);
4931 }
4932
fp_FieldBuildIdRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4933 fp_FieldBuildIdRun::fp_FieldBuildIdRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4934 {
4935 }
4936
calculateValue(void)4937 bool fp_FieldBuildIdRun::calculateValue(void)
4938 {
4939 UT_UTF8String szFieldValue(XAP_App::s_szBuild_ID);
4940 if (getField())
4941 getField()->setValue(static_cast<const gchar*>(XAP_App::s_szBuild_ID));
4942 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4943 }
4944
fp_FieldBuildVersionRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4945 fp_FieldBuildVersionRun::fp_FieldBuildVersionRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4946 {
4947 }
4948
calculateValue(void)4949 bool fp_FieldBuildVersionRun::calculateValue(void)
4950 {
4951 UT_UTF8String szFieldValue(XAP_App::s_szBuild_Version);
4952 if (getField())
4953 getField()->setValue(static_cast<const gchar*>(XAP_App::s_szBuild_Version));
4954 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4955 }
4956
fp_FieldBuildOptionsRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4957 fp_FieldBuildOptionsRun::fp_FieldBuildOptionsRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4958 {
4959 }
4960
calculateValue(void)4961 bool fp_FieldBuildOptionsRun::calculateValue(void)
4962 {
4963 UT_UTF8String szFieldValue(XAP_App::s_szBuild_Options);
4964 if (getField())
4965 getField()->setValue(static_cast<const gchar*>(XAP_App::s_szBuild_Options));
4966 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4967 }
4968
fp_FieldBuildTargetRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4969 fp_FieldBuildTargetRun::fp_FieldBuildTargetRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4970 {
4971 }
4972
calculateValue(void)4973 bool fp_FieldBuildTargetRun::calculateValue(void)
4974 {
4975 UT_UTF8String szFieldValue(XAP_App::s_szBuild_Target);
4976 if (getField())
4977 getField()->setValue(static_cast<const gchar*>(XAP_App::s_szBuild_Target));
4978 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4979 }
4980
fp_FieldBuildCompileDateRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4981 fp_FieldBuildCompileDateRun::fp_FieldBuildCompileDateRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4982 {
4983 }
4984
calculateValue(void)4985 bool fp_FieldBuildCompileDateRun::calculateValue(void)
4986 {
4987 UT_UTF8String szFieldValue(XAP_App::s_szBuild_CompileDate);
4988 if (getField())
4989 getField()->setValue(static_cast<const gchar*>(XAP_App::s_szBuild_CompileDate));
4990 return _setValue(szFieldValue.ucs4_str().ucs4_str());
4991 }
4992
fp_FieldBuildCompileTimeRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)4993 fp_FieldBuildCompileTimeRun::fp_FieldBuildCompileTimeRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
4994 {
4995 }
4996
calculateValue(void)4997 bool fp_FieldBuildCompileTimeRun::calculateValue(void)
4998 {
4999 UT_UTF8String szFieldValue(XAP_App::s_szBuild_CompileTime);
5000 if (getField())
5001 getField()->setValue(static_cast<const gchar*>(XAP_App::s_szBuild_CompileTime));
5002 return _setValue(szFieldValue.ucs4_str().ucs4_str());
5003 }
5004
5005
5006 // Refers to an footnote in the main body of the text.
fp_FieldFootnoteRefRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5007 fp_FieldFootnoteRefRun::fp_FieldFootnoteRefRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5008 {
5009 const PP_AttrProp * pp = getSpanAP();
5010 UT_return_if_fail(pp);
5011
5012 const gchar * footid;
5013 bool bRes = pp->getAttribute("footnote-id", footid);
5014
5015 if(!bRes || !footid)
5016 {
5017 UT_DEBUGMSG(("fp_FieldFootnoteRefRun::fp_FieldFootnoteRefRun: Missing footnote-id attribute. Probably a malformed file.\n"));
5018 return;
5019 }
5020 m_iPID = atol(footid);
5021
5022 // see bug 9793
5023 _setDirection(pBL->getDominantDirection());
5024 }
5025
5026
calculateValue(void)5027 bool fp_FieldFootnoteRefRun::calculateValue(void)
5028 {
5029 const PP_AttrProp * pp = getSpanAP();
5030 if(pp == NULL)
5031 {
5032 return false;
5033 }
5034 const gchar * footid = NULL;
5035 bool bRes = pp->getAttribute("footnote-id", footid);
5036
5037 if(!bRes || !footid)
5038 {
5039 UT_DEBUGMSG(("fp_FieldFootnoteRefRun::calculateValue: Missing footnote-id attribute. Probably a malformed file.\n"));
5040 return false;
5041 }
5042 FV_View * pView = _getView();
5043 UT_uint32 iPID = atoi(footid);
5044 const gchar *szCitation = NULL;
5045 bool bHaveCitation = pp->getAttribute("text:note-citation", szCitation);
5046 UT_sint32 footnoteNo = bHaveCitation ?
5047 atoi(szCitation) : pView->getLayout()->getFootnoteVal(iPID);
5048
5049 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
5050 sz_ucs_FieldValue[0] = 0;
5051
5052 UT_String sFieldValue;
5053 FootnoteType iFootType = pView->getLayout()->getFootnoteType();
5054 pView->getLayout()->getStringFromFootnoteVal(sFieldValue,footnoteNo,iFootType);
5055 UT_UCS4_strcpy_char(sz_ucs_FieldValue, sFieldValue.c_str());
5056
5057 return _setValue(sz_ucs_FieldValue);
5058 }
5059
canBreakBefore(void) const5060 bool fp_FieldFootnoteRefRun::canBreakBefore(void) const
5061 {
5062 return false;
5063 }
5064
fp_FieldFootnoteAnchorRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5065 fp_FieldFootnoteAnchorRun::fp_FieldFootnoteAnchorRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5066 {
5067 const PP_AttrProp * pp = getSpanAP();
5068 UT_return_if_fail(pp);
5069
5070 const gchar * footid = NULL;
5071 bool bRes = pp->getAttribute("footnote-id", footid);
5072
5073 if(!bRes || !footid)
5074 {
5075 UT_DEBUGMSG(("fp_FieldFootnoteAnchorRun::fp_FieldFootnoteAnchorRun: Missing footnote-id attribute. Probably a malformed file.\n"));
5076 return;
5077 }
5078 m_iPID = atol(footid);
5079
5080 // see bug 9793
5081 _setDirection(pBL->getDominantDirection());
5082 }
5083
5084 // Appears in the FootnoteContainer, one per footnote.
calculateValue(void)5085 bool fp_FieldFootnoteAnchorRun::calculateValue(void)
5086 {
5087 const PP_AttrProp * pp = getSpanAP();
5088 UT_return_val_if_fail(pp, false);
5089
5090 const gchar * footid = NULL;
5091 bool bRes = pp->getAttribute("footnote-id", footid);
5092
5093 if(!bRes || !footid)
5094 {
5095 UT_DEBUGMSG(("fp_FieldFootnoteAnchorRun::calculateValue: Missing footnote-id attribute. Probably a malformed file.\n"));
5096 return false;
5097 }
5098 UT_uint32 iPID = atoi(footid);
5099 FV_View * pView = _getView();
5100 const gchar *szCitation = NULL;
5101 bool bHaveCitation = pp->getAttribute("text:note-citation", szCitation);
5102 UT_sint32 footnoteNo = bHaveCitation ?
5103 atoi(szCitation) : pView->getLayout()->getFootnoteVal(iPID);
5104
5105 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
5106 sz_ucs_FieldValue[0] = 0;
5107
5108 FootnoteType iFootType = pView->getLayout()->getFootnoteType();
5109
5110 UT_String sFieldValue;
5111 pView->getLayout()->getStringFromFootnoteVal(sFieldValue,footnoteNo,iFootType);
5112 UT_UCS4_strcpy_char(sz_ucs_FieldValue, sFieldValue.c_str());
5113
5114 return _setValue(sz_ucs_FieldValue);
5115 }
5116
5117
fp_FieldEndnoteAnchorRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5118 fp_FieldEndnoteAnchorRun::fp_FieldEndnoteAnchorRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5119 {
5120 const PP_AttrProp * pp = getSpanAP();
5121 UT_return_if_fail(pp);
5122
5123 const gchar * footid = NULL;
5124 bool bRes = pp->getAttribute("endnote-id", footid);
5125
5126 if(!bRes || !footid)
5127 {
5128 UT_DEBUGMSG(("fp_FieldEndnoteAnchorRun::fp_FieldEndnoteAnchorRun: Missing endnote-id attribute. Probably a malformed file.\n"));
5129 return;
5130 }
5131 m_iPID = atoi(footid);
5132
5133 // see bug 9793
5134 _setDirection(pBL->getDominantDirection());
5135 }
5136
5137 // Appears in the EndnoteSection, one per endnote.
calculateValue(void)5138 bool fp_FieldEndnoteAnchorRun::calculateValue(void)
5139 {
5140 const PP_AttrProp * pp = getSpanAP();
5141 UT_return_val_if_fail(pp, false);
5142
5143 const gchar * footid = NULL;
5144 bool bRes = pp->getAttribute("endnote-id", footid);
5145
5146 if(!bRes || !footid)
5147 {
5148 UT_DEBUGMSG(("fp_FieldEndnoteAnchorRun::calculateValue: Missing endnote-id attribute. Probably a malformed file.\n"));
5149 return false;
5150 }
5151 UT_uint32 iPID = atoi(footid);
5152 FV_View * pView = _getView();
5153 UT_sint32 endnoteNo = pView->getLayout()->getEndnoteVal(iPID);
5154
5155 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
5156 sz_ucs_FieldValue[0] = 0;
5157
5158 FootnoteType iEndType = pView->getLayout()->getEndnoteType();
5159
5160 UT_String sFieldValue;
5161 pView->getLayout()->getStringFromFootnoteVal(sFieldValue,endnoteNo,iEndType);
5162 UT_UCS4_strcpy_char(sz_ucs_FieldValue, sFieldValue.c_str());
5163
5164 return _setValue(sz_ucs_FieldValue);
5165 }
5166
5167
fp_FieldEndnoteRefRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5168 fp_FieldEndnoteRefRun::fp_FieldEndnoteRefRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5169 {
5170 const PP_AttrProp * pp = getSpanAP();
5171 UT_return_if_fail(pp);
5172
5173 const gchar * footid;
5174 bool bRes = pp->getAttribute("endnote-id", footid);
5175
5176 if(!bRes || !footid)
5177 {
5178 UT_DEBUGMSG(("fp_FieldEndnoteRefRun::fp_FieldEndnoteRefRun: Missing endnote-id attribute. Probably a malformed file.\n"));
5179 return;
5180 }
5181 m_iPID = atoi(footid);
5182
5183 // see bug 9793
5184 _setDirection(pBL->getDominantDirection());
5185 }
5186
5187 // Appears in the EndnoteSection, one per endnote.
calculateValue(void)5188 bool fp_FieldEndnoteRefRun::calculateValue(void)
5189 {
5190 const PP_AttrProp * pp = getSpanAP();
5191 UT_return_val_if_fail(pp, false);
5192
5193 const gchar * footid = NULL;
5194 bool bRes = pp->getAttribute("endnote-id", footid);
5195
5196 if(!bRes || !footid)
5197 {
5198 UT_DEBUGMSG(("fp_FieldEndnoteRefRun::calculateValue: Missing endnote-id attribute. Probably a malformed file.\n"));
5199 return false;
5200 }
5201 UT_uint32 iPID = atoi(footid);
5202 FV_View * pView = _getView();
5203 UT_sint32 endnoteNo = pView->getLayout()->getEndnoteVal(iPID);
5204
5205 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
5206 sz_ucs_FieldValue[0] = 0;
5207
5208 FootnoteType iEndType = pView->getLayout()->getEndnoteType();
5209
5210 UT_String sFieldValue;
5211 pView->getLayout()->getStringFromFootnoteVal(sFieldValue,endnoteNo,iEndType);
5212 UT_UCS4_strcpy_char(sz_ucs_FieldValue, sFieldValue.c_str());
5213
5214 return _setValue(sz_ucs_FieldValue);
5215 }
5216
canBreakBefore(void) const5217 bool fp_FieldEndnoteRefRun::canBreakBefore(void) const
5218 {
5219 return false;
5220 }
5221
fp_FieldTimeRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5222 fp_FieldTimeRun::fp_FieldTimeRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5223 {
5224 }
5225
calculateValue(void)5226 bool fp_FieldTimeRun::calculateValue(void)
5227 {
5228 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
5229 sz_ucs_FieldValue[0] = 0;
5230
5231 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
5232
5233 time_t tim = time(NULL);
5234 struct tm *pTime = localtime(&tim);
5235
5236 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%X", pTime);
5237 if (getField())
5238 getField()->setValue(static_cast<const gchar*>(szFieldValue));
5239
5240 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
5241
5242 return _setValue(sz_ucs_FieldValue);
5243 }
5244
fp_FieldDateRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5245 fp_FieldDateRun::fp_FieldDateRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5246 {
5247 }
5248
calculateValue(void)5249 bool fp_FieldDateRun::calculateValue(void)
5250 {
5251 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
5252 sz_ucs_FieldValue[0] = 0;
5253
5254 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
5255
5256 time_t tim = time(NULL);
5257 struct tm *pTime = localtime(&tim);
5258
5259 strftime(szFieldValue, FPFIELD_MAX_LENGTH, "%A %B %d, %Y", pTime);
5260 if (getField())
5261 getField()->setValue(static_cast<const gchar*>(szFieldValue));
5262
5263 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
5264
5265 return _setValue(sz_ucs_FieldValue);
5266 }
5267
fp_FieldFileNameRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5268 fp_FieldFileNameRun::fp_FieldFileNameRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5269 {
5270 }
5271
calculateValue(void)5272 bool fp_FieldFileNameRun::calculateValue(void)
5273 {
5274 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
5275 sz_ucs_FieldValue[0] = 0;
5276
5277 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
5278
5279 PD_Document * pDoc = getBlock()->getDocument();
5280 UT_return_val_if_fail(pDoc, false);
5281
5282 //copy in the name or some wierd char instead
5283 const char * name = pDoc->getFilename();
5284 if (!name)
5285 name = "*";
5286
5287 strncpy (szFieldValue, name, FPFIELD_MAX_LENGTH);
5288 szFieldValue[FPFIELD_MAX_LENGTH] = '\0';
5289
5290 if (getField())
5291 getField()->setValue(static_cast<const gchar*>(szFieldValue));
5292
5293 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
5294
5295 return _setValue(sz_ucs_FieldValue);
5296 }
5297
fp_FieldShortFileNameRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5298 fp_FieldShortFileNameRun::fp_FieldShortFileNameRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5299 {
5300 }
5301
calculateValue(void)5302 bool fp_FieldShortFileNameRun::calculateValue(void)
5303 {
5304 UT_UCSChar sz_ucs_FieldValue[FPFIELD_MAX_LENGTH + 1];
5305 sz_ucs_FieldValue[0] = 0;
5306
5307 char szFieldValue[FPFIELD_MAX_LENGTH + 1];
5308
5309 PD_Document * pDoc = getBlock()->getDocument();
5310 UT_return_val_if_fail(pDoc, false);
5311
5312 //copy in the name or some wierd char instead
5313 const char * name = UT_go_basename_from_uri(pDoc->getFilename());
5314 if (!name)
5315 name = "*";
5316
5317 strncpy (szFieldValue, name, FPFIELD_MAX_LENGTH);
5318 szFieldValue[FPFIELD_MAX_LENGTH] = '\0';
5319
5320 if (getField())
5321 getField()->setValue(static_cast<const gchar*>(szFieldValue));
5322
5323 UT_UCS4_strcpy_char(sz_ucs_FieldValue, szFieldValue);
5324
5325 return _setValue(sz_ucs_FieldValue);
5326 }
5327
fp_FieldPageNumberRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5328 fp_FieldPageNumberRun::fp_FieldPageNumberRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5329 {
5330 }
5331
calculateValue(void)5332 bool fp_FieldPageNumberRun::calculateValue(void)
5333 {
5334 UT_UTF8String szFieldValue ("?");
5335
5336 if (getLine() && getLine()->getContainer() && getLine()->getContainer()->getPage())
5337 {
5338 fp_Page* pPage = getLine()->getContainer()->getPage();
5339 pPage->resetFieldPageNumber();
5340 UT_sint32 iPageNum = pPage->getFieldPageNumber();
5341 if (iPageNum > 0)
5342 {
5343 UT_UTF8String_sprintf(szFieldValue, "%d", iPageNum);
5344 }
5345 }
5346
5347 if (getField())
5348 getField()->setValue(static_cast<const gchar*>(szFieldValue.utf8_str()));
5349
5350 return _setValue(szFieldValue.ucs4_str().ucs4_str());
5351 }
5352
5353 ////////////////////////////////////////////////////////////////////////////
5354 ///////////////////////////////////////////////////////////////////////////
5355
fp_FieldPageReferenceRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5356 fp_FieldPageReferenceRun::fp_FieldPageReferenceRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen)
5357 : fp_FieldRun(pBL, iOffsetFirst, iLen)
5358 {
5359 }
5360
calculateValue(void)5361 bool fp_FieldPageReferenceRun::calculateValue(void)
5362 {
5363 UT_UTF8String szFieldValue ("?");
5364
5365 if(!_getParameter())
5366 return false;
5367
5368 FV_View * pView = _getView();
5369 // on import the field value can be requested before the View exists
5370 // so we cannot assert here
5371 //UT_ASSERT(pView);
5372 if(!pView)
5373 return false;
5374
5375 fp_Run* pRun = NULL;
5376 fl_BlockLayout * pBlock;
5377 fl_SectionLayout * pSection = pView->getLayout()->getFirstSection();
5378 UT_ASSERT(pSection);
5379 bool bFound = false;
5380
5381 while (pSection)
5382 {
5383 pBlock = static_cast<fl_BlockLayout *>(pSection->getFirstLayout());
5384
5385 while (pBlock)
5386 {
5387 pRun = pBlock->getFirstRun();
5388 while (pRun)
5389 {
5390 xxx_UT_DEBUGMSG(("pRun 0x%x, type %d\n", pRun, pRun->getType()));
5391 if(pRun->getType() == FPRUN_BOOKMARK)
5392 {
5393 fp_BookmarkRun * pB = static_cast<fp_BookmarkRun*>(pRun);
5394 if(pB->isStartOfBookmark() && !strcmp(_getParameter(),pB->getName()))
5395 {
5396 bFound = true;
5397 break;
5398 }
5399 }
5400 pRun = pRun->getNextRun();
5401 }
5402 if(bFound)
5403 break;
5404
5405 pBlock = static_cast<fl_BlockLayout *>(pBlock->getNext());
5406 }
5407 if(bFound)
5408 break;
5409 pSection = static_cast<fl_SectionLayout *>(pSection->getNext());
5410 }
5411
5412 if( pRun
5413 && pRun->getLine()
5414 && pRun->getLine()->getContainer()
5415 && pRun->getLine()->getContainer()->getPage())
5416 {
5417 fp_Page* pPage = pRun->getLine()->getContainer()->getPage();
5418 FL_DocLayout* pDL = pPage->getDocLayout();
5419
5420 UT_sint32 iPageNum = 0;
5421 UT_uint32 iNumPages = pDL->countPages();
5422 for (UT_uint32 i=0; i<iNumPages; i++)
5423 {
5424 fp_Page* pPg = pDL->getNthPage(i);
5425
5426 if (pPg == pPage)
5427 {
5428 iPageNum = i + 1;
5429 break;
5430 }
5431 }
5432 UT_UTF8String_sprintf(szFieldValue, "%d", iPageNum);
5433 }
5434 else
5435 {
5436 const XAP_StringSet * pSS = XAP_App::getApp()->getStringSet();
5437 std::string Msg1;
5438 pSS->getValue(AP_STRING_ID_FIELD_Error, XAP_App::getApp()->getDefaultEncoding(), Msg1);
5439
5440 std::string Msg2;
5441 pSS->getValue(AP_STRING_ID_MSG_BookmarkNotFound, XAP_App::getApp()->getDefaultEncoding(), Msg2);
5442 std::string format = UT_std_string_sprintf("{%s: %s}", Msg1.c_str(), Msg2.c_str());
5443 UT_UTF8String_sprintf(szFieldValue, format.c_str(), _getParameter());
5444 }
5445
5446 if (getField())
5447 getField()->setValue(static_cast<const gchar*>(szFieldValue.utf8_str()));
5448
5449 return _setValue(szFieldValue.ucs4_str().ucs4_str());
5450 }
5451
5452
5453 ///////////////////////////////////////////////////////////////////////////
5454
fp_FieldPageCountRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5455 fp_FieldPageCountRun::fp_FieldPageCountRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldRun(pBL, iOffsetFirst, iLen)
5456 {
5457 }
5458
calculateValue(void)5459 bool fp_FieldPageCountRun::calculateValue(void)
5460 {
5461 UT_UTF8String szFieldValue ("?");
5462
5463 if (getLine() && getLine()->getContainer() && getLine()->getContainer()->getPage())
5464 {
5465
5466 fp_Page* pPage = getLine()->getContainer()->getPage();
5467 FL_DocLayout* pDL = pPage->getDocLayout();
5468
5469 UT_UTF8String_sprintf(szFieldValue, "%d", pDL->countPages());
5470 }
5471
5472 if (getField())
5473 getField()->setValue(static_cast<const gchar*>(szFieldValue.utf8_str()));
5474
5475 return _setValue(szFieldValue.ucs4_str().ucs4_str());
5476 }
5477
5478 //////////////////////////////////////////////////////////////////
5479 //////////////////////////////////////////////////////////////////
5480
fp_FieldMailMergeRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5481 fp_FieldMailMergeRun::fp_FieldMailMergeRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen)
5482 : fp_FieldRun(pBL, iOffsetFirst, iLen)
5483 {
5484 }
5485
calculateValue(void)5486 bool fp_FieldMailMergeRun::calculateValue(void)
5487 {
5488 fd_Field * fld = getField();
5489 if (fld) {
5490 const gchar * param = fld->getParameter ();
5491
5492 if (!param)
5493 return false;
5494
5495 UT_UTF8String value ;
5496
5497 PD_Document * pDoc = getBlock()->getDocument();
5498 UT_ASSERT(pDoc);
5499
5500 if (!pDoc->mailMergeFieldExists(param))
5501 {
5502 // we'll take this branch if there's no mapping, we'll display
5503 // the field name instead
5504 value = "<";
5505 value += param;
5506 value += ">";
5507 }
5508 else
5509 {
5510 value = pDoc->getMailMergeField(param);
5511 }
5512
5513 fld->setValue(static_cast<const gchar*>(value.utf8_str()));
5514
5515 return _setValue(value.ucs4_str().ucs4_str());
5516 }
5517
5518 return false;
5519 }
5520
5521 //////////////////////////////////////////////////////////////////
5522 //////////////////////////////////////////////////////////////////
5523
fp_FieldMetaRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen,const char * which)5524 fp_FieldMetaRun::fp_FieldMetaRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen, const char * which)
5525 : fp_FieldRun(pBL, iOffsetFirst, iLen), m_which(which)
5526 {
5527 }
5528
calculateValue(void)5529 bool fp_FieldMetaRun::calculateValue(void)
5530 {
5531 PD_Document * pDoc = getBlock()->getDocument();
5532 UT_ASSERT(pDoc);
5533
5534 std::string value ;
5535 if (!pDoc->getMetaDataProp(m_which, value) || value.empty())
5536 value = " ";
5537
5538 if (getField())
5539 getField()->setValue(value.c_str());
5540
5541 return _setValue(UT_UCS4String(value).ucs4_str());
5542 }
5543
fp_FieldMetaTitleRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5544 fp_FieldMetaTitleRun::fp_FieldMetaTitleRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_TITLE)
5545 {
5546 }
5547
fp_FieldMetaCreatorRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5548 fp_FieldMetaCreatorRun::fp_FieldMetaCreatorRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_CREATOR)
5549 {
5550 }
5551
fp_FieldMetaSubjectRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5552 fp_FieldMetaSubjectRun::fp_FieldMetaSubjectRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_SUBJECT)
5553 {
5554 }
5555
fp_FieldMetaPublisherRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5556 fp_FieldMetaPublisherRun::fp_FieldMetaPublisherRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_PUBLISHER)
5557 {
5558 }
5559
fp_FieldMetaDateRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5560 fp_FieldMetaDateRun::fp_FieldMetaDateRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_DATE)
5561 {
5562 }
5563
fp_FieldMetaDateLastChangedRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5564 fp_FieldMetaDateLastChangedRun::fp_FieldMetaDateLastChangedRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_DATE_LAST_CHANGED)
5565 {
5566 }
5567
fp_FieldMetaTypeRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5568 fp_FieldMetaTypeRun::fp_FieldMetaTypeRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_TYPE)
5569 {
5570 }
5571
fp_FieldMetaLanguageRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5572 fp_FieldMetaLanguageRun::fp_FieldMetaLanguageRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_LANGUAGE)
5573 {
5574 }
5575
fp_FieldMetaRightsRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5576 fp_FieldMetaRightsRun::fp_FieldMetaRightsRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_RIGHTS)
5577 {
5578 }
5579
fp_FieldMetaKeywordsRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5580 fp_FieldMetaKeywordsRun::fp_FieldMetaKeywordsRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_KEYWORDS)
5581 {
5582 }
5583
fp_FieldMetaContributorRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5584 fp_FieldMetaContributorRun::fp_FieldMetaContributorRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_CONTRIBUTOR)
5585 {
5586 }
5587
fp_FieldMetaCoverageRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5588 fp_FieldMetaCoverageRun::fp_FieldMetaCoverageRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_COVERAGE)
5589 {
5590 }
5591
fp_FieldMetaDescriptionRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5592 fp_FieldMetaDescriptionRun::fp_FieldMetaDescriptionRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_FieldMetaRun(pBL, iOffsetFirst, iLen, PD_META_KEY_DESCRIPTION)
5593 {
5594 }
5595
5596 //////////////////////////////////////////////////////////////////
5597 //////////////////////////////////////////////////////////////////
5598
fp_ForcedColumnBreakRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5599 fp_ForcedColumnBreakRun::fp_ForcedColumnBreakRun(fl_BlockLayout* pBL,UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_Run(pBL, iOffsetFirst, iLen, FPRUN_FORCEDCOLUMNBREAK)
5600 {
5601 lookupProperties();
5602 }
5603
_lookupProperties(const PP_AttrProp *,const PP_AttrProp *,const PP_AttrProp *,GR_Graphics *)5604 void fp_ForcedColumnBreakRun::_lookupProperties(const PP_AttrProp * /*pSpanAP*/,
5605 const PP_AttrProp * /*pBlockAP*/,
5606 const PP_AttrProp * /*pSectionAP*/,
5607 GR_Graphics *)
5608 {
5609 fd_Field * fd = NULL;
5610
5611 getBlock()->getField(getBlockOffset(),fd);
5612 _setField(fd);
5613
5614 _inheritProperties();
5615 _setWidth(1);
5616 }
5617
canBreakAfter(void) const5618 bool fp_ForcedColumnBreakRun::canBreakAfter(void) const
5619 {
5620 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
5621
5622 return false;
5623 }
5624
canBreakBefore(void) const5625 bool fp_ForcedColumnBreakRun::canBreakBefore(void) const
5626 {
5627 UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
5628
5629 return false;
5630 }
5631
_letPointPass(void) const5632 bool fp_ForcedColumnBreakRun::_letPointPass(void) const
5633 {
5634 return false;
5635 }
5636
mapXYToPosition(UT_sint32,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)5637 void fp_ForcedColumnBreakRun::mapXYToPosition(UT_sint32 /* x */, UT_sint32 /*y*/, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool& /*isTOC*/)
5638 {
5639 pos = getBlock()->getPosition() + getBlockOffset();
5640 bBOL = false;
5641 bEOL = false;
5642 }
5643
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)5644 void fp_ForcedColumnBreakRun::findPointCoords(UT_uint32 iOffset, UT_sint32& x, UT_sint32& y, UT_sint32& x2, UT_sint32& y2, UT_sint32& height, bool& bDirection)
5645 {
5646 //UT_DEBUGMSG(("fintPointCoords: ForcedColumnBreakRun\n"));
5647 UT_ASSERT(getBlockOffset() == iOffset || getBlockOffset()+1 == iOffset);
5648
5649 UT_sint32 xoff, yoff;
5650
5651 fp_Run* pPropRun = _findPrevPropertyRun();
5652
5653 if (pPropRun)
5654 {
5655 if(FPRUN_TEXT == pPropRun->getType())
5656 {
5657 pPropRun->findPointCoords(iOffset, x, y, x2, y2, height, bDirection);
5658 }
5659 else
5660 {
5661 height = getHeight();
5662 getLine()->getOffsets(this, xoff, yoff);
5663 x = xoff;
5664 y = yoff;
5665 }
5666 }
5667 else
5668 {
5669 height = getHeight();
5670 getLine()->getOffsets(this, xoff, yoff);
5671 x = xoff;
5672 y = yoff;
5673 }
5674
5675 x2 = x;
5676 y2 = y;
5677 }
5678
_clearScreen(bool)5679 void fp_ForcedColumnBreakRun::_clearScreen(bool /* bFullLineHeightRect */)
5680 {
5681 // UT_ASSERT(!isDirty());
5682 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
5683
5684 UT_sint32 xoff = 0, yoff = 0;
5685 getLine()->getScreenOffsets(this, xoff, yoff);
5686 UT_sint32 iWidth = getLine()->getMaxWidth() - getLine()->calculateWidthOfLine();
5687 Fill(getGraphics(),xoff,yoff,iWidth,getLine()->getHeight());
5688 }
5689
_draw(dg_DrawArgs * pDA)5690 void fp_ForcedColumnBreakRun::_draw(dg_DrawArgs* pDA)
5691 {
5692 GR_Graphics * pG = pDA->pG;
5693 if (!(pG->queryProperties(GR_Graphics::DGP_SCREEN))){
5694 return;
5695 }
5696
5697 FV_View* pView = _getView();
5698 UT_ASSERT(pView);
5699 if(!pView->getShowPara()){
5700 return;
5701 }
5702
5703 UT_sint32 iLineWidth = getLine()->getMaxWidth();
5704
5705 const XAP_StringSet *pSS = XAP_App::getApp()->getStringSet();
5706 std::string s;
5707 pSS->getValueUTF8(AP_STRING_ID_BREAK_Column, s);
5708 UT_UCSChar *pColumnBreak;
5709 UT_UCS4_cloneString_char(&pColumnBreak, s.c_str());
5710 _drawTextLine(pDA->xoff,pDA->yoff+getLine()->getAscent(),iLineWidth,getLine()->getHeight(),pColumnBreak);
5711 FREEP(pColumnBreak);
5712 }
5713
5714 //////////////////////////////////////////////////////////////////
5715 //////////////////////////////////////////////////////////////////
5716
fp_ForcedPageBreakRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_uint32 iLen)5717 fp_ForcedPageBreakRun::fp_ForcedPageBreakRun(fl_BlockLayout* pBL, UT_uint32 iOffsetFirst, UT_uint32 iLen) : fp_Run(pBL, iOffsetFirst, iLen, FPRUN_FORCEDPAGEBREAK)
5718 {
5719 lookupProperties();
5720 }
5721
_lookupProperties(const PP_AttrProp *,const PP_AttrProp *,const PP_AttrProp *,GR_Graphics *)5722 void fp_ForcedPageBreakRun::_lookupProperties(const PP_AttrProp * /*pSpanAP*/,
5723 const PP_AttrProp * /*pBlockAP*/,
5724 const PP_AttrProp * /*pSectionAP*/,
5725 GR_Graphics *)
5726 {
5727 fd_Field * fd = NULL;
5728
5729 getBlock()->getField(getBlockOffset(),fd);
5730 _setField(fd);
5731
5732 _inheritProperties();
5733 _setWidth(1);
5734 }
5735
canBreakAfter(void) const5736 bool fp_ForcedPageBreakRun::canBreakAfter(void) const
5737 {
5738 return false;
5739 }
5740
canBreakBefore(void) const5741 bool fp_ForcedPageBreakRun::canBreakBefore(void) const
5742 {
5743 return false;
5744 }
5745
_letPointPass(void) const5746 bool fp_ForcedPageBreakRun::_letPointPass(void) const
5747 {
5748 return false;
5749 }
5750
mapXYToPosition(UT_sint32,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)5751 void fp_ForcedPageBreakRun::mapXYToPosition(UT_sint32 /* x */, UT_sint32 /*y*/, PT_DocPosition& pos, bool& bBOL, bool& bEOL, bool& /*isTOC*/)
5752 {
5753 //TODO: Find everything that calls this and modify them to allow y-axis.
5754 pos = getBlock()->getPosition() + getBlockOffset();
5755 bBOL = false;
5756 bEOL = false;
5757 }
5758
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)5759 void fp_ForcedPageBreakRun::findPointCoords(UT_uint32 iOffset, UT_sint32& x, UT_sint32& y, UT_sint32& x2, UT_sint32& y2, UT_sint32& height, bool& bDirection)
5760 {
5761 //UT_DEBUGMSG(("fintPointCoords: ForcedPageBreakRun\n"));
5762 UT_ASSERT(getBlockOffset() == iOffset || getBlockOffset()+1 == iOffset);
5763
5764 UT_sint32 xoff, yoff;
5765
5766 fp_Run* pPropRun = _findPrevPropertyRun();
5767
5768 if (pPropRun)
5769 {
5770 height = pPropRun->getHeight();
5771 if(FPRUN_TEXT == pPropRun->getType())
5772 {
5773 pPropRun->findPointCoords(iOffset, x, y, x2, y2, height, bDirection);
5774 }
5775 else
5776 {
5777 height = getHeight();
5778 getLine()->getOffsets(this, xoff, yoff);
5779 x = xoff;
5780 y = yoff;
5781 }
5782 }
5783 else
5784 {
5785 height = getHeight();
5786 getLine()->getOffsets(this, xoff, yoff);
5787 x = xoff;
5788 y = yoff;
5789 }
5790
5791 if (iOffset == getBlockOffset()+1)
5792 {
5793 FV_View* pView = _getView();
5794 if (pView->getShowPara())
5795 {
5796 x += getWidth();
5797 }
5798 }
5799
5800 x2 = x;
5801 y2 = y;
5802 }
5803
_clearScreen(bool)5804 void fp_ForcedPageBreakRun::_clearScreen(bool /* bFullLineHeightRect */)
5805 {
5806 // UT_ASSERT(!isDirty());
5807 UT_ASSERT(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
5808
5809 UT_sint32 xoff = 0, yoff = 0;
5810 getLine()->getScreenOffsets(this, xoff, yoff);
5811 UT_sint32 iWidth = getLine()->getMaxWidth() - getLine()->calculateWidthOfLine();
5812 Fill(getGraphics(),xoff,yoff,iWidth,getLine()->getHeight());
5813 }
5814
_draw(dg_DrawArgs * pDA)5815 void fp_ForcedPageBreakRun::_draw(dg_DrawArgs* pDA)
5816 {
5817 GR_Graphics * pG = pDA->pG;
5818
5819 if (!(pG->queryProperties(GR_Graphics::DGP_SCREEN))){
5820 return;
5821 }
5822
5823 FV_View* pView = _getView();
5824 UT_ASSERT(pView);
5825 if(!pView->getShowPara()){
5826 return;
5827 }
5828
5829 UT_sint32 iLineWidth = getLine()->getMaxWidth();
5830
5831 const XAP_StringSet *pSS = XAP_App::getApp()->getStringSet();
5832 std::string s;
5833 pSS->getValueUTF8(AP_STRING_ID_BREAK_Page, s);
5834 UT_UCSChar *pPageBreak;
5835 UT_UCS4_cloneString_char(&pPageBreak, s.c_str());
5836
5837 _drawTextLine(pDA->xoff,pDA->yoff+getLine()->getAscent(),iLineWidth,getLine()->getHeight(),pPageBreak);
5838 FREEP(pPageBreak);
5839 }
5840
5841 // translates logical position in a run into visual position
5842 // (will also translate correctly visual -> logical)
getVisPosition(UT_uint32 iLogPos) const5843 UT_uint32 fp_Run::getVisPosition(UT_uint32 iLogPos) const
5844 {
5845 if(getVisDirection() == UT_BIDI_RTL) //rtl needs translation
5846 {
5847 return (getLength() - iLogPos - 1);
5848 }
5849 else return (iLogPos);
5850 }
5851
5852 //translates a visual position in a span of length iLen to logical pos
5853 //or vice versa
getVisPosition(UT_uint32 iLogPos,UT_uint32 iLen) const5854 UT_uint32 fp_Run::getVisPosition(UT_uint32 iLogPos, UT_uint32 iLen) const
5855 {
5856 if(getVisDirection() == UT_BIDI_RTL) //rtl needs translation
5857 {
5858 return (iLen - iLogPos - 1);
5859 }
5860 else return (iLogPos);
5861 }
5862
5863 //returns the logical offset of the first visual character
getOffsetFirstVis() const5864 UT_uint32 fp_Run::getOffsetFirstVis() const
5865 {
5866 if(getVisDirection() == UT_BIDI_RTL) //rtl, requires translation
5867 {
5868 return(getBlockOffset() + getLength() - 1);
5869 }
5870 else return (getBlockOffset());
5871 }
5872
5873 //translates visual offset to logical one, can be also used for translation
5874 //in the other direction
getOffsetLog(UT_uint32 iVisOff) const5875 UT_uint32 fp_Run::getOffsetLog(UT_uint32 iVisOff) const
5876 {
5877 if(getVisDirection() == UT_BIDI_RTL) //rtl needs translation
5878 {
5879 return(getBlockOffset() + getLength() - iVisOff + getBlockOffset() - 1);
5880 }
5881 else return (iVisOff);
5882 }
5883
getNextVisual()5884 fp_Run * fp_Run::getNextVisual()
5885 {
5886 if(!getLine())
5887 return NULL;
5888
5889 UT_uint32 iIndxVis = getLine()->getVisIndx(this);
5890
5891 return getLine()->getRunAtVisPos(iIndxVis + 1);
5892 }
5893
getPrevVisual()5894 fp_Run * fp_Run::getPrevVisual()
5895 {
5896 if(!getLine())
5897 return NULL;
5898
5899 UT_uint32 iIndxVis = getLine()->getVisIndx(this);
5900
5901 if(!iIndxVis)
5902 return NULL;
5903
5904 return getLine()->getRunAtVisPos(iIndxVis - 1);
5905 }
5906
setDirection(UT_BidiCharType iDir)5907 void fp_Run::setDirection(UT_BidiCharType iDir)
5908 {
5909 xxx_UT_DEBUGMSG(("fp_Run::SetDirection, getDirection() %d, iDir %d, run type %d\n", getDirection(), iDir, getType()));
5910 UT_BidiCharType iDirection = iDir != static_cast<UT_BidiCharType>(UT_BIDI_UNSET) ? iDir : UT_BIDI_WS;
5911 if(getDirection() != iDirection)
5912 {
5913 UT_BidiCharType origDirection = getDirection();
5914 _setDirection(iDirection);
5915 clearScreen();
5916 /*
5917 if this run belongs to a line we have to notify the line that
5918 that it now contains a run of this direction, if it does not belong
5919 to a line this will be taken care of by the fp_Line:: member function
5920 used to add the run to the line (generally, we set it here if this
5921 is a run that is being typed in and it gets set in the member
5922 functions when the run is loaded from a document on the disk.)
5923 */
5924
5925 if(getLine())
5926 getLine()->changeDirectionUsed(origDirection,getDirection(),true);
5927 }
5928 }
5929
5930 // returns the direction with which the run is displayed,
getVisDirection() const5931 UT_BidiCharType fp_Run::getVisDirection() const
5932 {
5933 #ifndef NO_BIDI_SUPPORT
5934 FV_View * pView = _getView();
5935 if(pView && pView->getBidiOrder() != FV_Order_Visual)
5936 {
5937 if(pView->getBidiOrder() == FV_Order_Logical_LTR)
5938 return UT_BIDI_LTR;
5939 else
5940 return UT_BIDI_RTL;
5941 }
5942 else if(m_iVisDirection == static_cast<UT_BidiCharType>(UT_BIDI_UNSET))
5943 {
5944 if(m_pLine)
5945 {
5946 m_pLine->_createMapOfRuns();
5947 UT_ASSERT(m_iVisDirection != static_cast<UT_BidiCharType>(UT_BIDI_UNSET));
5948 return m_iVisDirection;
5949 }
5950 else if(getBlock())
5951 return getBlock()->getDominantDirection();
5952 else
5953 {
5954 bool b;
5955 XAP_App::getApp()->getPrefsValueBool(static_cast<const gchar*>(AP_PREF_KEY_DefaultDirectionRtl), &b);
5956 if(b)
5957 return UT_BIDI_RTL;
5958 else
5959 return UT_BIDI_LTR;
5960 }
5961 }
5962 else
5963 return m_iVisDirection;
5964 #else
5965 return UT_BIDI_LTR;
5966 #endif
5967 }
5968
setVisDirection(UT_BidiCharType iDir)5969 void fp_Run::setVisDirection(UT_BidiCharType iDir)
5970 {
5971 if( iDir != m_iVisDirection
5972 && m_iVisDirection != static_cast<UT_BidiCharType>(UT_BIDI_UNSET)
5973 /*&& m_eRefreshDrawBuffer == GRSR_BufferClean*/)
5974 {
5975 // the text in the buffer is in the wrong order, schedule it
5976 // for refresh
5977 m_eRefreshDrawBuffer = GRSR_Unknown;
5978 }
5979
5980 m_iVisDirection = iDir;
5981 }
5982
5983 #if 0
5984 void fp_Run::setDirectionProperty(UT_BidiCharType dir)
5985 {
5986 const gchar * prop[] = {NULL, NULL, 0};
5987 const gchar direction[] = "dir";
5988 const gchar rtl[] = "rtl";
5989 const gchar ltr[] = "ltr";
5990 UT_String other;
5991
5992 prop[0] = static_cast<const gchar*>(&direction);
5993
5994 switch(dir)
5995 {
5996 case UT_BIDI_LTR: prop[1] = static_cast<const gchar*>(<r); break;
5997 case UT_BIDI_RTL: prop[1] = static_cast<const gchar*>(&rtl); break;
5998 default:
5999 {
6000 // for anything other we will print the UT_BidiCharType value
6001 // this will allow us to coallesce runs of same type without
6002 // having to list here tons of possible strings
6003 // (we could do this for rtl and ltr as well, but "rtl" and "ltr"
6004 // are much more informative.)
6005 UT_String_sprintf(other,"fbt%d",static_cast<UT_uint32>(dir));
6006 prop[1] = static_cast<const gchar*>(other.c_str()); break;
6007 }
6008 };
6009
6010 UT_uint32 offset = getBlock()->getPosition() + getBlockOffset();
6011 getBlock()->getDocument()->changeSpanFmt(PTC_AddFmt,offset,offset + getLength(),NULL,prop);
6012 UT_DEBUGMSG(("fp_Run::setDirectionProperty: offset=%d, len=%d, dir=\"%s\"\n", offset,getLength(),prop[1]));
6013 }
6014 #endif
6015
6016 /*!
6017 The following function allows us to respond to deletion of part of
6018 a run in a smart way; this is just default implementation, and
6019 there is nothing smart about it, derrived classes should provide
6020 their own implementation where it makes sense (see fp_TextRun)
6021
6022 \param offset: run offset at which deletion starts
6023 \param iLen: length of the deleted section, can reach past the
6024 end of the run
6025 */
updateOnDelete(UT_uint32 offset,UT_uint32 iLenToDelete)6026 void fp_Run::updateOnDelete(UT_uint32 offset, UT_uint32 iLenToDelete)
6027 {
6028 // do not try to delete past the end of the run ...
6029 UT_return_if_fail(offset < m_iLen);
6030
6031 UT_uint32 iLen = UT_MIN(iLenToDelete, m_iLen - offset);
6032
6033 // do not try to delete nothing ...
6034 if(iLen == 0)
6035 return;
6036
6037 setLength(m_iLen - iLen, true);
6038 }
6039
6040 // house keeping
6041 #undef FPRUN_PROPS_MINI_DUMP
6042