1 /* AbiWord
2 * Copyright (C) 2003 Tomas Frydrych <tomas@frydrych.uklinux.net>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA.
18 */
19
20 #include "fp_DirectionMarkerRun.h"
21 #include "fl_BlockLayout.h"
22 #include "fp_TextRun.h"
23 #include "fp_Line.h"
24 #include "fv_View.h"
25
26 #include "gr_DrawArgs.h"
27 #include "gr_Graphics.h"
28
29 #include "ut_debugmsg.h"
30 #include "ut_assert.h"
31 #include "gr_Painter.h"
32
fp_DirectionMarkerRun(fl_BlockLayout * pBL,UT_uint32 iOffsetFirst,UT_UCS4Char cMarker)33 fp_DirectionMarkerRun::fp_DirectionMarkerRun(fl_BlockLayout* pBL,
34 UT_uint32 iOffsetFirst,
35 UT_UCS4Char cMarker):
36 fp_Run(pBL, iOffsetFirst, 1, FPRUN_DIRECTIONMARKER)
37 {
38 m_iMarker = cMarker;
39
40 _setDirty(true);
41 _setDirection(UT_bidiGetCharType(m_iMarker));
42 lookupProperties();
43 }
44
45
_recalcWidth(void)46 bool fp_DirectionMarkerRun::_recalcWidth(void)
47 {
48 UT_sint32 iOldWidth = getWidth();
49 FV_View* pView = _getView();
50
51 if (pView && pView->getShowPara())
52 {
53 if(static_cast<UT_sint32>(m_iDrawWidth) != iOldWidth)
54 {
55 _setWidth(m_iDrawWidth);
56 return true;
57 }
58
59 xxx_UT_DEBUGMSG(("fp_DirectionMarkerRun::lookupProperties: width %d\n", getWidth()));
60 }
61 else
62 {
63 if(iOldWidth != 0)
64 {
65 _setWidth(0);
66 return true;
67 }
68 }
69
70 return false;
71 }
72
_lookupProperties(const PP_AttrProp * pSpanAP,const PP_AttrProp * pBlockAP,const PP_AttrProp * pSectionAP,GR_Graphics * pG)73 void fp_DirectionMarkerRun::_lookupProperties(const PP_AttrProp * pSpanAP,
74 const PP_AttrProp * pBlockAP,
75 const PP_AttrProp * pSectionAP,
76 GR_Graphics * pG)
77 {
78 //UT_DEBUGMSG(("fp_DirectionMarkerRun::lookupProperties\n"));
79 _inheritProperties();
80 if(pG == NULL)
81 {
82 pG = getGraphics();
83 }
84 const gchar* pRevision = NULL;
85
86 if(pBlockAP && pBlockAP->getAttribute("revision", pRevision))
87 {
88 // we will not in fact be doing anything with the actual
89 // properties and attributes contained in the revision
90 // we just need its representation so the base class can
91 // handle us properly
92 PP_RevisionAttr * pRev = getRevisions();
93 DELETEP(pRev);
94
95 _setRevisions(new PP_RevisionAttr(pRevision));
96 }
97
98 // Find drawing width
99 fp_Run* pPropRun = _findPrevPropertyRun();
100 if (pPropRun && (FPRUN_TEXT == pPropRun->getType()))
101 {
102 fp_TextRun* pTextRun = static_cast<fp_TextRun*>(pPropRun);
103 pG->setFont(pTextRun->getFont());
104 }
105 else
106 {
107 // look for fonts in this DocLayout's font cache
108 FL_DocLayout * pLayout = getBlock()->getDocLayout();
109
110 const GR_Font * pFont = pLayout->findFont(pSpanAP,pBlockAP,pSectionAP);
111 pG->setFont(pFont);
112 }
113
114 UT_UCS4Char cM = m_iMarker == UCS_LRM ? (UT_UCS4Char)'>' : (UT_UCS4Char)'<';
115 m_iDrawWidth = pG->measureString(&cM, 0, 1, NULL);
116 xxx_UT_DEBUGMSG(("fp_DirectionMarkerRun::lookupProperties: width %d\n", getWidth()));
117 }
118
canBreakAfter(void) const119 bool fp_DirectionMarkerRun::canBreakAfter(void) const
120 {
121 return true;
122 }
123
canBreakBefore(void) const124 bool fp_DirectionMarkerRun::canBreakBefore(void) const
125 {
126 return true;
127 }
128
_letPointPass(void) const129 bool fp_DirectionMarkerRun::_letPointPass(void) const
130 {
131 return false;
132 }
133
_deleteFollowingIfAtInsPoint() const134 bool fp_DirectionMarkerRun::_deleteFollowingIfAtInsPoint() const
135 {
136 // we will only allow deletion if visible on screen
137 FV_View* pView = _getView();
138 if(!pView || !pView->getShowPara())
139 {
140 return true;
141 }
142
143 return false;
144 }
145
mapXYToPosition(UT_sint32 x,UT_sint32,PT_DocPosition & pos,bool & bBOL,bool & bEOL,bool &)146 void fp_DirectionMarkerRun::mapXYToPosition(UT_sint32 x,
147 UT_sint32 /*y*/,
148 PT_DocPosition& pos,
149 bool& bBOL,
150 bool& bEOL,
151 bool & /*isTOC*/)
152 {
153 if (x > getWidth())
154 pos = getBlock()->getPosition() + getBlockOffset() + getLength();
155 else
156 pos = getBlock()->getPosition() + getBlockOffset();
157
158 bBOL = false;
159 bEOL = false;
160 }
161
findPointCoords(UT_uint32 iOffset,UT_sint32 & x,UT_sint32 & y,UT_sint32 & x2,UT_sint32 & y2,UT_sint32 & height,bool & bDirection)162 void fp_DirectionMarkerRun::findPointCoords(UT_uint32 iOffset,
163 UT_sint32& x, UT_sint32& y,
164 UT_sint32& x2, UT_sint32& y2,
165 UT_sint32& height,
166 bool& bDirection)
167 {
168 fp_Run* pPropRun = _findPrevPropertyRun();
169
170 height = getHeight();
171
172 if (pPropRun)
173 {
174 height = pPropRun->getHeight();
175 // If property Run is on the same line, get y location from
176 // it (to reflect proper ascent).
177 if (pPropRun->getLine() == getLine())
178 {
179 if(FPRUN_TEXT == pPropRun->getType())
180 {
181 pPropRun->findPointCoords(iOffset, x, y, x2, y2, height, bDirection);
182 return;
183 }
184 }
185 }
186
187 getLine()->getOffsets(this, x, y);
188 x2 = x;
189 y2 = y;
190 bDirection = (getVisDirection() != UT_BIDI_LTR);
191 }
192
_clearScreen(bool)193 void fp_DirectionMarkerRun::_clearScreen(bool /* bFullLineHeightRect */)
194 {
195 UT_return_if_fail(getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN));
196
197 GR_Painter painter(getGraphics());
198
199 if(getWidth())
200 {
201 UT_sint32 xoff = 0, yoff = 0;
202 getLine()->getScreenOffsets(this, xoff, yoff);
203
204 if(getVisDirection() == UT_BIDI_RTL)
205 {
206 xoff -= m_iDrawWidth;
207 }
208 painter.fillRect(_getColorPG(), xoff, yoff+1, m_iDrawWidth, getLine()->getHeight()+1);
209 }
210 }
211
212 /*!
213 Draw Direction marker graphical representation
214 \param pDA Draw arguments
215 Draws the < or > character in show paragraphs mode.
216 */
_draw(dg_DrawArgs * pDA)217 void fp_DirectionMarkerRun::_draw(dg_DrawArgs* pDA)
218 {
219 // if showPara is turned off we will not draw anything at all; however,
220 // we will ensure that the width is set to 0, and if it is currently not
221 // we will get our line to redo its layout and redraw.
222 FV_View* pView = _getView();
223 if(!pView || !pView->getShowPara())
224 {
225 return;
226 }
227
228 GR_Painter painter(getGraphics());
229
230 UT_ASSERT_HARMLESS(pDA->pG == getGraphics());
231
232 UT_uint32 iRunBase = getBlock()->getPosition() + getBlockOffset();
233
234 UT_uint32 iSelAnchor = pView->getSelectionAnchor();
235 UT_uint32 iPoint = pView->getPoint();
236
237 UT_uint32 iSel1 = UT_MIN(iSelAnchor, iPoint);
238 UT_uint32 iSel2 = UT_MAX(iSelAnchor, iPoint);
239
240 UT_ASSERT_HARMLESS(iSel1 <= iSel2);
241
242 bool bIsSelected = false;
243 if (/* pView->getFocus()!=AV_FOCUS_NONE && */ (iSel1 <= iRunBase) && (iSel2 > iRunBase))
244 bIsSelected = true;
245
246 UT_sint32 iAscent;
247
248 fp_Run* pPropRun = _findPrevPropertyRun();
249 if (pPropRun && (FPRUN_TEXT == pPropRun->getType()))
250 {
251 fp_TextRun* pTextRun = static_cast<fp_TextRun*>(pPropRun);
252 getGraphics()->setFont(pTextRun->getFont());
253 iAscent = pTextRun->getAscent();
254 }
255 else
256 {
257 const PP_AttrProp * pSpanAP = NULL;
258 const PP_AttrProp * pBlockAP = NULL;
259 const PP_AttrProp * pSectionAP = NULL;
260 getSpanAP(pSpanAP);
261 getBlockAP(pBlockAP);
262 // look for fonts in this DocLayout's font cache
263 FL_DocLayout * pLayout = getBlock()->getDocLayout();
264
265 const GR_Font * pFont = pLayout->findFont(pSpanAP,pBlockAP,pSectionAP);
266 getGraphics()->setFont(pFont);
267 iAscent = getGraphics()->getFontAscent();
268 }
269
270 // if we currently have a 0 width, i.e., we draw in response to the
271 // showPara being turned on, then we obtain the new width, and then
272 // tell the line to redo its layout and redraw instead of drawing ourselves
273 UT_UCS4Char cM = m_iMarker == UCS_LRM ? (UT_UCS4Char)'>' : (UT_UCS4Char)'<';
274 m_iDrawWidth = getGraphics()->measureString(&cM, 0, 1, NULL);
275
276 _setHeight(getGraphics()->getFontHeight());
277 m_iXoffText = pDA->xoff;
278
279 m_iYoffText = pDA->yoff - iAscent;
280 xxx_UT_DEBUGMSG(("fp_DirectionMarkerRun::draw: width %d\n", m_iDrawWidth));
281
282 if (bIsSelected)
283 {
284 painter.fillRect(_getView()->getColorSelBackground(),
285 m_iXoffText,
286 m_iYoffText,
287 m_iDrawWidth,
288 getLine()->getHeight());
289 }
290 else
291 {
292 painter.fillRect(_getColorPG(),
293 m_iXoffText,
294 m_iYoffText,
295 m_iDrawWidth,
296 getLine()->getHeight());
297 }
298 if (pView->getShowPara())
299 {
300 // Draw symbol
301 // use the hard-coded colour only if not revised
302 if(!getRevisions())
303 getGraphics()->setColor(pView->getColorShowPara());
304 painter.drawChars(&cM, 0, 1, m_iXoffText, m_iYoffText);
305 }
306 }
307