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*>(&ltr);     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