1 /* AbiWord
2 * Copyright (c) 2003 Martin Sevior <msevior@physics.unimelb.edu.au>
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 <math.h>
21 #include "fv_VisualDragText.h"
22 #include "fl_DocLayout.h"
23 #include "pd_Document.h"
24 #include "gr_Graphics.h"
25 #include "ut_units.h"
26 #include "fl_BlockLayout.h"
27 #include "fp_Line.h"
28 #include "fp_Run.h"
29 #include "fl_TableLayout.h"
30 #include "fp_TableContainer.h"
31 #include "fv_View.h"
32 #include "gr_Painter.h"
33 #include "xap_Frame.h"
34 #include "fv_ViewDoubleBuffering.h"
35
36 #define MIN_DRAG_PIXELS 8
37
FV_VisualDragText(FV_View * pView)38 FV_VisualDragText::FV_VisualDragText (FV_View * pView)
39 : m_pView (pView),
40 m_iVisualDragMode(FV_VisualDrag_NOT_ACTIVE),
41 m_pDragImage(NULL),
42 m_iLastX(0),
43 m_iLastY(0),
44 m_recCurFrame(0,0,0,0),
45 m_iInitialOffX(0),
46 m_iInitialOffY(0),
47 m_recOrigLeft(0,0,0,0),
48 m_recOrigRight(0,0,0,0),
49 m_bTextCut(false),
50 m_pDocUnderCursor(NULL),
51 m_bCursorDrawn(false),
52 m_recCursor(0,0,0,0),
53 m_pAutoScrollTimer(NULL),
54 m_xLastMouse(1),
55 m_yLastMouse(1),
56 m_bDoingCopy(false),
57 m_bNotDraggingImage(false),
58 m_bSelectedRow(false)
59 {
60 UT_ASSERT_HARMLESS(pView);
61 }
62
~FV_VisualDragText()63 FV_VisualDragText::~FV_VisualDragText()
64 {
65 DELETEP(m_pDragImage);
66 if(m_pAutoScrollTimer != NULL)
67 {
68 m_pAutoScrollTimer->stop();
69 DELETEP(m_pAutoScrollTimer);
70 }
71 }
72
isActive(void) const73 bool FV_VisualDragText::isActive(void) const
74 {
75 return (FV_VisualDrag_NOT_ACTIVE != m_iVisualDragMode);
76 }
77
getGraphics(void) const78 GR_Graphics * FV_VisualDragText::getGraphics(void) const
79 {
80 return m_pView->getGraphics();
81 }
82
setMode(FV_VisualDragMode iEditMode)83 void FV_VisualDragText::setMode(FV_VisualDragMode iEditMode)
84 {
85 m_iVisualDragMode = iEditMode;
86 if(iEditMode == FV_VisualDrag_NOT_ACTIVE)
87 {
88 m_iInitialOffX = 0;
89 m_iInitialOffY = 0;
90 m_iLastX = 0;
91 m_iLastY = 0;
92 m_xLastMouse = 0;
93 m_yLastMouse = 0;
94 }
95 }
96
97 static UT_sint32 iExtra = 0;
98 static bool bScrollRunning = false;
99 static UT_Worker * s_pScroll = NULL;
100
_actuallyScroll(UT_Worker * pWorker)101 void FV_VisualDragText::_actuallyScroll(UT_Worker * pWorker)
102 {
103 UT_return_if_fail(pWorker);
104
105 // this is a static callback method and does not have a 'this' pointer.
106
107 FV_VisualDragText * pVis = static_cast<FV_VisualDragText *>(pWorker->getInstanceData());
108 UT_return_if_fail(pVis);
109 FV_View * pView = pVis->m_pView;
110 pVis->getGraphics()->setClipRect(&pVis->m_recCurFrame);
111 pView->updateScreen(false);
112 pView->getGraphics()->setClipRect(NULL);
113 bool bScrollDown = false;
114 bool bScrollUp = false;
115 bool bScrollLeft = false;
116 bool bScrollRight = false;
117 UT_sint32 y = pVis->m_yLastMouse;
118 UT_sint32 x = pVis->m_xLastMouse;
119 if(y<=0)
120 {
121 bScrollUp = true;
122 }
123 else if(y >= pView->getWindowHeight())
124 {
125 bScrollDown = true;
126 }
127 if(x <= 0)
128 {
129 bScrollLeft = true;
130 }
131 else if(x >= pView->getWindowWidth())
132 {
133 bScrollRight = true;
134 }
135
136 if(bScrollDown || bScrollUp || bScrollLeft || bScrollRight)
137 {
138 UT_sint32 minScroll = pView->getGraphics()->tlu(20);
139
140 if(bScrollUp)
141 {
142 UT_sint32 yscroll = abs(y);
143 if(yscroll < minScroll)
144 yscroll = minScroll;
145 pView->cmdScroll(AV_SCROLLCMD_LINEUP, static_cast<UT_uint32>( yscroll) + iExtra);
146 }
147 else if(bScrollDown)
148 {
149 UT_sint32 yscroll = y - pView->getWindowHeight();
150 if(yscroll < minScroll)
151 yscroll = minScroll;
152 pView->cmdScroll(AV_SCROLLCMD_LINEDOWN, static_cast<UT_uint32>(yscroll) + iExtra);
153 }
154 if(bScrollLeft)
155 {
156 pView->cmdScroll(AV_SCROLLCMD_LINELEFT, static_cast<UT_uint32>(-x));
157 }
158 else if(bScrollRight)
159 {
160 pView->cmdScroll(AV_SCROLLCMD_LINERIGHT, static_cast<UT_uint32>(x -pView->getWindowWidth()));
161 }
162 pVis->drawImage();
163 #if 0
164 PT_DocPosition posAtXY = pVis->getPosFromXY(x,y);
165 pView->_setPoint(posAtXY);
166 pVis->drawCursor(posAtXY);
167 #endif
168 iExtra = 0;
169 return;
170 }
171 else
172 {
173 if(pVis->m_pAutoScrollTimer)
174 pVis->m_pAutoScrollTimer->stop();
175 DELETEP(pVis->m_pAutoScrollTimer);
176 }
177 s_pScroll->stop();
178 delete s_pScroll;
179 s_pScroll = NULL;
180 bScrollRunning = false;
181 iExtra = 0;
182
183 }
184
_autoScroll(UT_Worker * pWorker)185 void FV_VisualDragText::_autoScroll(UT_Worker * pWorker)
186 {
187
188 // this is a static callback method and does not have a 'this' pointer.
189
190 UT_return_if_fail(pWorker);
191 FV_VisualDragText * pVis = static_cast<FV_VisualDragText *>(pWorker->getInstanceData());
192 UT_return_if_fail(pVis);
193 if(bScrollRunning)
194 {
195 UT_DEBUGMSG(("Dropping VisualDragText autoscroll !!!!!!! \n"));
196 if(iExtra < pVis->getGraphics()->tlu(600))
197 iExtra += pVis->getGraphics()->tlu(20);
198 return;
199 }
200
201 int inMode = UT_WorkerFactory::IDLE | UT_WorkerFactory::TIMER;
202 UT_WorkerFactory::ConstructMode outMode = UT_WorkerFactory::NONE;
203 s_pScroll = UT_WorkerFactory::static_constructor (_actuallyScroll,pVis, inMode, outMode);
204
205 // If the worker is working on a timer instead of in the idle
206 // time, set the frequency of the checks.
207 if ( UT_WorkerFactory::TIMER == outMode )
208 {
209 // this is really a timer, so it's safe to static_cast it
210 static_cast<UT_Timer*>(s_pScroll)->set(100);
211 }
212 bScrollRunning = true;
213 iExtra = 0;
214 s_pScroll->start();
215 }
216
mouseDrag(UT_sint32 x,UT_sint32 y)217 void FV_VisualDragText::mouseDrag(UT_sint32 x, UT_sint32 y)
218 {
219 _mouseDrag(x,y);
220 }
221
_mouseDrag(UT_sint32 x,UT_sint32 y)222 void FV_VisualDragText::_mouseDrag(UT_sint32 x, UT_sint32 y)
223 {
224 //
225 // Don't try to drag the entire document.
226 //
227 if(!m_bDoingCopy && (m_pView->isSelectAll() && !m_pView->isHdrFtrEdit())&&(m_iVisualDragMode != FV_VisualDrag_DRAGGING))
228 {
229 setMode(FV_VisualDrag_NOT_ACTIVE);
230 return;
231 }
232
233 if(m_iVisualDragMode == FV_VisualDrag_NOT_ACTIVE)
234 {
235 m_iInitialOffX = x;
236 m_iInitialOffY = y;
237 m_iVisualDragMode = FV_VisualDrag_WAIT_FOR_MOUSE_DRAG;
238 UT_DEBUGMSG(("Initial call for drag -1\n"));
239 return;
240 }
241 if((m_iInitialOffX == 0) && (m_iInitialOffY == 0))
242 {
243 m_iInitialOffX = x;
244 m_iInitialOffY = y;
245 m_iVisualDragMode = FV_VisualDrag_WAIT_FOR_MOUSE_DRAG;
246 UT_DEBUGMSG(("Initial call for drag -2 \n"));
247 }
248 if(m_iVisualDragMode == FV_VisualDrag_WAIT_FOR_MOUSE_DRAG)
249 {
250 double diff = sqrt((static_cast<double>(x) - static_cast<double>(m_iInitialOffX))*(static_cast<double>(x) - static_cast<double>(m_iInitialOffX)) +
251 (static_cast<double>(y) - static_cast<double>(m_iInitialOffY))*(static_cast<double>(y) - static_cast<double>(m_iInitialOffY)));
252 if(diff < static_cast<double>(getGraphics()->tlu(MIN_DRAG_PIXELS)))
253 {
254 UT_DEBUGMSG(("Not yet dragged enough.%f \n", diff));
255 //
256 // Have to drag 4 pixels before initiating the drag
257 //
258 return;
259 }
260 else
261 {
262 m_iVisualDragMode = FV_VisualDrag_START_DRAGGING;
263 XAP_Frame * pFrame = static_cast<XAP_Frame*>(m_pView->getParentData());
264 if (pFrame)
265 pFrame->dragText();
266 }
267 }
268 if((m_iVisualDragMode != FV_VisualDrag_DRAGGING) && (m_iVisualDragMode != FV_VisualDrag_WAIT_FOR_MOUSE_DRAG) && !m_bDoingCopy)
269 {
270 //
271 // Haven't started the drag yet so create our image and cut the text.
272 //
273 m_pView->getDocument()->beginUserAtomicGlob();
274 mouseCut(m_iInitialOffX,m_iInitialOffY);
275 m_bTextCut = true;
276
277 }
278 clearCursor();
279 if(m_iVisualDragMode == FV_VisualDrag_START_DRAGGING)
280 {
281 reposOffsets(x,y);
282 }
283 m_iVisualDragMode = FV_VisualDrag_DRAGGING;
284 xxx_UT_DEBUGMSG(("x = %d y = %d width \n",x,y));
285 bool bScrollDown = false;
286 bool bScrollUp = false;
287 bool bScrollLeft = false;
288 bool bScrollRight = false;
289 m_xLastMouse = x;
290 m_yLastMouse = y;
291 if(y<=0)
292 {
293 bScrollUp = true;
294 }
295 else if( y >= m_pView->getWindowHeight())
296 {
297 bScrollDown = true;
298 }
299 if(x <= 0)
300 {
301 bScrollLeft = true;
302 }
303 else if(x >= m_pView->getWindowWidth())
304 {
305 bScrollRight = true;
306 }
307 if(bScrollDown || bScrollUp || bScrollLeft || bScrollRight)
308 {
309 if(m_pAutoScrollTimer != NULL)
310 {
311 return;
312 }
313 m_pAutoScrollTimer = UT_Timer::static_constructor(_autoScroll, this);
314 m_pAutoScrollTimer->set(AUTO_SCROLL_MSECS);
315 m_pAutoScrollTimer->start();
316 return;
317 }
318 UT_sint32 dx = 0;
319 UT_sint32 dy = 0;
320 UT_Rect expX(0,m_recCurFrame.top,0,m_recCurFrame.height);
321 UT_Rect expY(m_recCurFrame.left,0,m_recCurFrame.width,0);
322 UT_sint32 iext = getGraphics()->tlu(3);
323 dx = x - m_iLastX;
324 dy = y - m_iLastY;
325 m_recCurFrame.left += dx;
326 m_recCurFrame.top += dy;
327 m_recOrigLeft.left += dx;
328 m_recOrigLeft.top += dy;
329 m_recOrigRight.left += dx;
330 m_recOrigRight.top += dy;
331 if(dx < 0)
332 {
333 expX.left = m_recCurFrame.left+m_recCurFrame.width -iext;
334 expX.width = -dx + 2*iext;
335 if(dy > 0)
336 {
337 expX.top -= iext;
338 expX.height += dy + 2*iext;
339 }
340 else
341 {
342 expX.top -= iext;
343 expX.height += (-dy + 2*iext);
344 }
345 }
346 else
347 {
348 expX.left = m_recCurFrame.left - dx - iext;
349 expX.width = dx + 2*iext;
350 if(dy > 0)
351 {
352 expX.top -= iext;
353 expX.height += dy + 2*iext;
354 }
355 else
356 {
357 expX.top -= iext;
358 expX.height += (-dy + 2*iext);
359 }
360 }
361 expY.left -= iext;
362 expY.width += 2*iext;
363 if(dy < 0)
364 {
365 expY.top = m_recCurFrame.top + m_recCurFrame.height -iext;
366 expY.height = -dy + 2*iext;
367 }
368 else
369 {
370 expY.top = m_recCurFrame.top - dy - iext;
371 expY.height = dy + 2*iext;
372 }
373
374 if(!m_bNotDraggingImage && (expX.width > 0))
375 {
376 getGraphics()->setClipRect(&expX);
377 if(m_bSelectedRow)
378
379 {
380 m_pView->setSelectionMode(FV_SelectionMode_NONE);
381 }
382 m_pView->updateScreen(false);
383 if(m_bSelectedRow)
384 {
385 m_pView->setSelectionMode(FV_SelectionMode_TableRow);
386 }
387
388 }
389 if(!m_bNotDraggingImage && (expY.height > 0))
390 {
391 xxx_UT_DEBUGMSG(("expY left %d top %d width %d height %d \n",expY.left,expY.top,expY.width,expY.height));
392 getGraphics()->setClipRect(&expY);
393 if(m_bSelectedRow)
394 {
395 m_pView->setSelectionMode(FV_SelectionMode_NONE);
396 }
397 m_pView->updateScreen(false);
398 if(m_bSelectedRow)
399 {
400 m_pView->setSelectionMode(FV_SelectionMode_TableRow);
401 }
402
403 }
404 if(!m_bNotDraggingImage && (expX.height > 0))
405 {
406 xxx_UT_DEBUGMSG(("expY left %d top %d width %d height %d \n",expX.left,expX.top,expX.width,expX.height));
407 getGraphics()->setClipRect(&expX);
408 if(m_bSelectedRow)
409 {
410 m_pView->setSelectionMode(FV_SelectionMode_NONE);
411 }
412 m_pView->updateScreen(false);
413 if(m_bSelectedRow)
414 {
415 m_pView->setSelectionMode(FV_SelectionMode_TableRow);
416 }
417
418 }
419 if(!m_bNotDraggingImage)
420 {
421 getGraphics()->setClipRect(NULL);
422 drawImage();
423 if(m_recOrigLeft.width > 0)
424 {
425 getGraphics()->setClipRect(&m_recOrigLeft);
426 m_pView->updateScreen(false);
427 }
428 if(m_recOrigRight.width > 0)
429 {
430 getGraphics()->setClipRect(&m_recOrigRight);
431 m_pView->updateScreen(false);
432 }
433 }
434 m_iLastX = x;
435 m_iLastY = y;
436 getGraphics()->setClipRect(NULL);
437 PT_DocPosition posAtXY = getPosFromXY(x,y);
438 m_pView->_setPoint(posAtXY);
439 xxx_UT_DEBUGMSG(("Point at visual drag set to %d \n",m_pView->getPoint()));
440 // m_pView->_fixInsertionPointCoords();
441 drawCursor(posAtXY);
442 }
443
444 /*!
445 * This method is called at the commencement of a visual drag. If the offsets
446 * to the caret are too big, this method will adjust them and shift the image
447 * of the dragged text to a comfortable distance fromthe caret.
448 * Returns true if the offsets are shifted.
449 * UT_sint32 x pos of the caret
450 * UT_sint32 y pos of the caret
451 */
reposOffsets(UT_sint32 x,UT_sint32 y)452 bool FV_VisualDragText::reposOffsets(UT_sint32 x, UT_sint32 y)
453 {
454 UT_sint32 dx = 0;
455 UT_sint32 dy = 0;
456 bool bAdjustX = false;
457 bool bAdjustY = false;
458 UT_sint32 iext = getGraphics()->tlu(3);
459 dx = x - m_recCurFrame.left - m_recOrigLeft.width;
460 dy = y - m_recCurFrame.top;
461 UT_DEBUGMSG((" repos dx = %d \n",dx));
462 UT_DEBUGMSG((" repos dy = %d \n",dy));
463 UT_Rect expX(0,m_recCurFrame.top,0,m_recCurFrame.height);
464 UT_Rect expY(m_recCurFrame.left,0,m_recCurFrame.width,0);
465 if(abs(dx) > getGraphics()->tlu(40))
466 {
467 bAdjustX = true;
468 dx -= getGraphics()->tlu(20);
469 m_iInitialOffX -= dx;
470 expX.set(0,m_recCurFrame.top,0,m_recCurFrame.height);
471 m_recCurFrame.left += dx;
472 m_recOrigLeft.left += dx;
473 m_recOrigRight.left += dx;
474 }
475 if(dy > getGraphics()->tlu(40))
476 {
477 bAdjustY = true;
478 dy -= getGraphics()->tlu(20);
479 m_iInitialOffY -= dy;
480 expY.set(m_recCurFrame.left,0,m_recCurFrame.width,0);
481 m_recCurFrame.top += dy;
482 m_recOrigLeft.top += dy;
483 m_recOrigRight.top += dy;
484 }
485
486 if(bAdjustX && dx < 0)
487 {
488 expX.left = m_recCurFrame.left+m_recCurFrame.width -iext;
489 expX.width = -dx + 2*iext;
490 if(dy > 0)
491 {
492 expX.top -= iext;
493 expX.height += dy + 2*iext;
494 }
495 else
496 {
497 expX.top -= iext;
498 expX.height += (-dy + 2*iext);
499 }
500 }
501 else if(bAdjustX)
502 {
503 expX.left = m_recCurFrame.left - dx - iext;
504 expX.width = dx + 2*iext;
505 if(dy > 0)
506 {
507 expX.top -= iext;
508 expX.height += dy + 2*iext;
509 }
510 else
511 {
512 expX.top -= iext;
513 expX.height += (-dy + 2*iext);
514 }
515 }
516 expY.left -= iext;
517 expY.width += 2*iext;
518 if(bAdjustY && dy < 0)
519 {
520 expY.top = m_recCurFrame.top + m_recCurFrame.height -iext;
521 expY.height = -dy + 2*iext;
522 }
523 else if(bAdjustY)
524 {
525 expY.top = m_recCurFrame.top - dy - iext;
526 expY.height = dy + 2*iext;
527 }
528
529 if(bAdjustX && expX.width > 0)
530 {
531 getGraphics()->setClipRect(&expX);
532 m_pView->updateScreen(false);
533 }
534 if(bAdjustY && (expY.height > 0))
535 {
536 getGraphics()->setClipRect(&expY);
537 m_pView->updateScreen(false);
538 }
539 if(bAdjustX || bAdjustY)
540 {
541 getGraphics()->setClipRect(NULL);
542 drawImage();
543 if(m_recOrigLeft.width > 0)
544 {
545 getGraphics()->setClipRect(&m_recOrigLeft);
546 m_pView->updateScreen(false);
547 }
548 if(m_recOrigRight.width > 0)
549 {
550 getGraphics()->setClipRect(&m_recOrigRight);
551 m_pView->updateScreen(false);
552 }
553 return true;
554 }
555 return false;
556 }
557
clearCursor(void)558 void FV_VisualDragText::clearCursor(void)
559 {
560 if(m_bCursorDrawn)
561 {
562 if(m_pDocUnderCursor)
563 {
564 getGraphics()->allCarets()->disable(true);
565 m_pView->m_countDisable++;
566 GR_Painter painter(getGraphics());
567 painter.drawImage(m_pDocUnderCursor,m_recDoc.left,m_recCursor.top);
568 m_bCursorDrawn = false;
569 DELETEP(m_pDocUnderCursor);
570 }
571 }
572 }
573
drawCursor(PT_DocPosition newPos)574 void FV_VisualDragText::drawCursor(PT_DocPosition newPos)
575 {
576 if(m_bCursorDrawn)
577 return;
578 getGraphics()->allCarets()->disable(true);
579 m_pView->m_countDisable++;
580 fp_Run * pRunLow = NULL;
581 fl_BlockLayout * pBlock = NULL;
582 UT_sint32 xLow, yLow;
583 UT_uint32 heightCaret;
584 UT_sint32 xCaret2, yCaret2;
585 bool bDirection=false;
586 bool bEOL=false;
587 m_pView->_findPositionCoords(newPos, bEOL, xLow, yLow, xCaret2, yCaret2, heightCaret, bDirection, &pBlock, &pRunLow);
588 m_recCursor.left = xLow;
589 m_recCursor.top = yLow;
590 m_recCursor.width = getGraphics()->tlu(2); // the cursor is 2 device units wide, not
591 // logical units
592 m_recCursor.height = heightCaret;
593 m_recDoc.left = xLow - getGraphics()->tlu(1);
594 m_recDoc.top = yLow - getGraphics()->tlu(1);
595 m_recDoc.width = getGraphics()->tlu(3);
596 m_recDoc.height = heightCaret + getGraphics()->tlu(1);
597 UT_ASSERT(m_pDocUnderCursor == NULL);
598 GR_Painter painter(getGraphics());
599 m_pDocUnderCursor = painter.genImageFromRectangle(m_recDoc);
600 UT_RGBColor black(0,0,0);
601 painter.fillRect( black, m_recCursor);
602 m_bCursorDrawn = true;
603 }
604
605 /*!
606 * This method creates an image from the current selection. It sets
607 * the drag rectangle, the initial offsets and the initial positions
608 * of the cursor.
609 */
getImageFromSelection(UT_sint32 x,UT_sint32 y)610 void FV_VisualDragText::getImageFromSelection(UT_sint32 x, UT_sint32 y)
611 {
612 //
613 // OK first work out the locations in the document of the anchor and point
614 //
615 PT_DocPosition posLow = 0;
616 PT_DocPosition posHigh = 0;
617
618 fp_Run * pRunLow = NULL;
619 UT_sint32 xLow, yLow,xHigh,yHigh;
620 UT_uint32 heightCaret;
621 UT_sint32 xCaret2, yCaret2;
622 bool bDirection = false;
623 bool bEOL = false;
624 fp_Page * pPageLow = NULL;
625 fp_Page * pPageHigh = NULL;
626 if(m_pView->getSelectionMode() < FV_SelectionMode_Multiple)
627 {
628 if(m_pView->getSelectionAnchor() < m_pView->getPoint())
629 {
630 posLow = m_pView->getSelectionAnchor();
631 posHigh = m_pView->getPoint();
632 }
633 else
634 {
635 posLow = m_pView->getPoint();
636 posHigh = m_pView->getSelectionAnchor();
637 }
638 }
639 else
640 {
641 UT_sint32 num = m_pView->getNumSelections();
642 PD_DocumentRange * pR = m_pView->getNthSelection(0);
643 posLow = pR->m_pos1+1;
644 fl_BlockLayout * pBlock = NULL;
645
646 bDirection = false;
647 bEOL = false;
648
649 m_pView->_findPositionCoords(posLow, bEOL, xLow, yLow, xCaret2, yCaret2, heightCaret, bDirection, &pBlock, &pRunLow);
650 while(pBlock->isEmbeddedType())
651 {
652 posLow++;
653 m_pView->_findPositionCoords(posLow, bEOL, xLow, yLow, xCaret2, yCaret2, heightCaret, bDirection, &pBlock, &pRunLow);
654 }
655 fl_ContainerLayout * pCL = pBlock->myContainingLayout();
656 UT_return_if_fail(pCL->getContainerType() == FL_CONTAINER_CELL);
657 fp_CellContainer * pCCon = static_cast<fp_CellContainer *>(pCL->getFirstContainer());
658 UT_return_if_fail(pCCon);
659 UT_Rect * pRect = pCCon->getScreenRect();
660 xLow = pRect->left;
661 yLow = pRect->top;
662 m_recCurFrame.left = xLow;
663 m_recCurFrame.top = yLow;
664 delete pRect;
665 //
666 // Now the other end of the column
667 //
668 pR = m_pView->getNthSelection(num-1);
669 posHigh = pR->m_pos1+1;
670 m_pView->_findPositionCoords(posHigh, bEOL, xHigh, yHigh, xCaret2, yCaret2, heightCaret, bDirection, &pBlock, &pRunLow);
671 while(pBlock->isEmbeddedType())
672 {
673 posHigh++;
674 m_pView->_findPositionCoords(posHigh, bEOL, xHigh, yHigh, xCaret2, yCaret2, heightCaret, bDirection, &pBlock, &pRunLow);
675 }
676 pCL = pBlock->myContainingLayout();
677 UT_return_if_fail(pCL->getContainerType() == FL_CONTAINER_CELL);
678 pCCon = static_cast<fp_CellContainer *>(pCL->getFirstContainer());
679 UT_return_if_fail(pCCon);
680 pRect = pCCon->getScreenRect();
681 xHigh = pRect->left+ pRect->width;
682 yHigh = pRect->top + pRect->height;
683 delete pRect;
684 m_recCurFrame.width = xHigh - xLow;
685 m_recCurFrame.height = yHigh - yLow;
686 m_recOrigLeft.width = 0;
687 m_recOrigLeft.height = 0;
688 m_recOrigLeft.left = 0;
689 m_recOrigLeft.top = 0;
690 m_recOrigRight.width = 0;
691 m_recOrigRight.height = 0;
692 m_recOrigRight.left = 0;
693 m_recOrigRight.top = 0;
694 m_iLastX = x;
695 m_iLastY = y;
696 m_iInitialOffX = x - m_recCurFrame.left;
697 m_iInitialOffY = y - m_recCurFrame.top;
698 GR_Painter painter(getGraphics());
699 m_pDragImage = painter.genImageFromRectangle(m_recCurFrame);
700 return;
701 }
702 fp_Run * pRunLow2 = NULL;
703 m_pView->_findPositionCoords(posLow+1, bEOL, xLow, yLow, xCaret2, yCaret2, heightCaret, bDirection, NULL, &pRunLow2);
704 UT_return_if_fail( pRunLow2 );
705 fl_BlockLayout * pBLow2 = pRunLow2->getBlock();
706 m_pView->_findPositionCoords(posLow, bEOL, xLow, yLow, xCaret2, yCaret2, heightCaret, bDirection, NULL, &pRunLow);
707 UT_return_if_fail( pRunLow );
708 fl_BlockLayout * pBLow1 = pRunLow->getBlock();
709 bool bUseNext = false;
710 bool bIsTable = false;
711 if(m_pView->getDocument()->isTableAtPos(posLow))
712 {
713 posLow += 2;
714 bIsTable = true;
715 }
716 fl_TableLayout * pTabLow = m_pView->getTableAtPos(posLow+1);
717 fl_TableLayout * pTabHigh = m_pView->getTableAtPos(posHigh);
718 if(bIsTable && (pTabLow != pTabHigh))
719 {
720 posLow -= 2;
721 }
722 if(pBLow2 != pBLow1)
723 {
724 pRunLow = pRunLow2;
725 bUseNext = true;
726 }
727 fp_Line * pLineLow = pRunLow->getLine();
728 fp_Run * pRunHigh = NULL;
729 m_pView->_findPositionCoords(posHigh, bEOL, xHigh, yHigh, xCaret2, yCaret2, heightCaret, bDirection, NULL, &pRunHigh);
730 fp_Line * pLineHigh = pRunHigh->getLine();
731 pPageLow = pLineLow->getPage();
732 pPageHigh = pLineHigh->getPage();
733 //
734 // Decide if the selection is fully on screen and all on the same page.
735 //
736 bool bOffscreen = false;
737 if(pPageLow != pPageHigh)
738 {
739 bOffscreen = true;
740 }
741 if(!bOffscreen && ((yLow <0) || (yHigh > m_pView->getWindowHeight())))
742 {
743 bOffscreen = true;
744 }
745 if(!bOffscreen && ((xLow <0) || (xHigh <0) || (xLow > m_pView->getWindowWidth()) ||(xLow > m_pView->getWindowWidth())))
746 {
747 bOffscreen = true;
748 }
749 if(bOffscreen)
750 {
751 m_bNotDraggingImage = true;
752 m_recCurFrame.left = x - 1;
753 m_recCurFrame.top = y - 1;
754 m_recCurFrame.width = 2;
755 m_recCurFrame.height = 2;
756 m_iInitialOffX = 1;
757 m_iInitialOffY = 1;
758 m_iLastX = x;
759 m_iLastY = y;
760 m_recOrigLeft.width = 2;
761 m_recOrigLeft.height = 2;
762 m_recOrigLeft.left = x-1;
763 m_recOrigLeft.top = y-1;
764 GR_Graphics::Cursor cursor = GR_Graphics::GR_CURSOR_DRAGTEXT;
765 if(isDoingCopy())
766 {
767 cursor = GR_Graphics::GR_CURSOR_COPYTEXT;
768 }
769 getGraphics()->setCursor(cursor);
770 return;
771 }
772 m_bNotDraggingImage = false;
773 //
774 // OK deal with the nice case of the selection just on the single line
775 //
776 bool bDoBroken = true;
777 if(pLineLow == pLineHigh)
778 {
779 //
780 // Grab that first charcter!
781 //
782 if(!bUseNext)
783 {
784 m_pView->_findPositionCoords(posLow, bEOL, xLow, yLow, xCaret2, yCaret2, heightCaret, bDirection, NULL, &pRunLow2);
785 }
786 else
787 {
788 m_pView->_findPositionCoords(posLow+1, bEOL, xLow, yLow, xCaret2, yCaret2, heightCaret, bDirection, NULL, &pRunLow2);
789 }
790 UT_sint32 xx,yy;
791 pLineLow->getScreenOffsets(pRunLow,xx,yy);
792 m_recCurFrame.left = xLow < xHigh ? xLow : xHigh;
793 m_recCurFrame.width = xHigh > xLow ? xHigh - xLow : xLow - xHigh;
794 m_recCurFrame.top = yy;
795 m_recCurFrame.height = pLineLow->getHeight();
796 m_recOrigLeft.width = 0;
797 m_recOrigLeft.height = 0;
798 m_recOrigLeft.left = 0;
799 m_recOrigLeft.top = 0;
800 m_recOrigRight.width = 0;
801 m_recOrigRight.height = 0;
802 m_recOrigRight.left = 0;
803 m_recOrigRight.top = 0;
804 bDoBroken = false;
805 }
806 if ( bDoBroken && (pTabLow != NULL) && (pTabHigh == pTabLow))
807 {
808 //
809 // Look to see if we have a rectangular table selection
810 //
811 UT_sint32 nExtra = 1;
812 if(m_pView->getDocument()->isTableAtPos(posLow+nExtra))
813 {
814 nExtra++;
815 }
816 if(m_pView->getDocument()->isCellAtPos(posLow+nExtra))
817 {
818 nExtra++;
819 }
820 if(m_pView->getDocument()->isBlockAtPos(posLow+nExtra))
821 {
822 nExtra++;
823 }
824 fp_CellContainer * pCellConLow = m_pView->getCellAtPos(posLow+nExtra);
825 if(pCellConLow == NULL)
826 goto do_broken;
827 fl_CellLayout * pCellLow = static_cast<fl_CellLayout *>(pCellConLow->getSectionLayout());
828 if(m_pView->getDocument()->isEndTableAtPos(posHigh-1))
829 {
830 posHigh--;
831 }
832 fp_CellContainer * pCellConHigh = m_pView->getCellAtPos(posHigh);
833 if(pCellConHigh == NULL)
834 goto do_broken;
835 fl_CellLayout * pCellHigh = static_cast<fl_CellLayout *>(pCellConHigh->getSectionLayout());
836 if((pCellLow->getPosition(true) >= (posLow -1)) &&
837 ((pCellHigh->getPosition(true) + pCellHigh->getLength()-1) <= (posHigh + 1) ))
838 {
839 UT_sint32 numCols = static_cast<fp_TableContainer *>(pCellConLow->getContainer())->getNumCols();
840 if(((pCellConLow->getLeftAttach() == 0) &&
841 (pCellConHigh->getRightAttach() == numCols)) ||
842 (pCellConLow->getTopAttach() == pCellConHigh->getTopAttach()))
843 {
844 //
845 // OK the low and high cells are fully selected.
846 //
847 UT_DEBUGMSG(("Fully selected low and high positions \n"));
848 //
849 // Grab that first charcter!
850 //
851 if(!bUseNext)
852 {
853 m_pView->_findPositionCoords(posLow, bEOL, xLow, yLow, xCaret2, yCaret2, heightCaret, bDirection, NULL, &pRunLow2);
854 }
855 else
856 {
857 m_pView->_findPositionCoords(posLow+1, bEOL, xLow, yLow, xCaret2, yCaret2, heightCaret, bDirection, NULL, &pRunLow2);
858 }
859 if((pCellConLow->getLeftAttach() == 0) &&
860 (pCellConHigh->getRightAttach() == numCols))
861 {
862 m_bSelectedRow = true;
863 }
864 UT_Rect * pLow = pCellConLow->getScreenRect();
865 UT_Rect * pHigh = pCellConHigh->getScreenRect();
866 UT_return_if_fail(pLow);
867 UT_return_if_fail(pHigh);
868 m_recCurFrame.left = pLow->left;
869 m_recCurFrame.width = pHigh->left + pHigh->width - pLow->left;
870 m_recCurFrame.top = pLow->top;
871 m_recCurFrame.height = pHigh->top + pHigh->height - pLow->top;
872 DELETEP(pLow);
873 DELETEP(pHigh);
874 m_recOrigLeft.width = 0;
875 m_recOrigLeft.height = 0;
876 m_recOrigLeft.left = 0;
877 m_recOrigLeft.top = 0;
878 m_recOrigRight.width = 0;
879 m_recOrigRight.height = 0;
880 m_recOrigRight.left = 0;
881 m_recOrigRight.top = 0;
882 bDoBroken = false;
883 }
884 }
885 }
886 do_broken: if(bDoBroken)
887 {
888 //
889 // low and high are on different rows. First get top, left
890 //
891 //
892 UT_sint32 xx,yy;
893 fp_Run * pRun = pLineLow->getFirstRun();
894 pLineLow->getScreenOffsets(pRun,xx,yy);
895 xx -= pRun->getX();
896 xx -= pLineLow->getX();
897 m_recOrigLeft.left = xx < xLow ? xx : xLow;
898 m_recOrigLeft.width = xLow > xx ? xLow - xx : xx - xLow;
899 m_recOrigLeft.top = yy;
900 m_recOrigLeft.height = pLineLow->getHeight();
901 m_recCurFrame.left = xx < xLow ? xx : xLow;
902 m_recCurFrame.top = yy;
903 fp_Line * pNext = pLineLow;
904 UT_sint32 width = 0;
905 while(pNext && (pNext != pLineHigh))
906 {
907 pRun = pNext->getFirstRun();
908 pNext->getScreenOffsets(pRun,xx,yy);
909 xx += pNext->getMaxWidth();
910 if(xx > width)
911 {
912 width = xx;
913 }
914 fp_ContainerObject * pCon = pNext->getNext();
915 if(pCon)
916 {
917 pNext = static_cast<fp_Line *>(pCon);
918 }
919 else
920 {
921 fl_BlockLayout * pBL = pNext->getBlock();
922 pBL = pBL->getNextBlockInDocument();
923 if(pBL)
924 {
925 pNext = static_cast<fp_Line *>(pBL->getFirstContainer());
926 }
927 else
928 {
929 pNext = NULL;
930 }
931 }
932 }
933 if(pNext == NULL)
934 {
935 UT_DEBUGMSG(("Last line of selection not found! \n"));
936 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
937 return;
938 }
939 pRun = pLineHigh->getFirstRun();
940 pLineHigh->getScreenOffsets(pRun,xx,yy);
941 yy += pLineHigh->getHeight();
942 m_recCurFrame.width = width > m_recCurFrame.left ? width - m_recCurFrame.left : m_recCurFrame.left - width;
943 m_recCurFrame.height = yy - m_recCurFrame.top;
944 if(m_recCurFrame.top + m_recCurFrame.height > m_pView->getWindowHeight())
945 {
946 m_recCurFrame.height = m_pView->getWindowHeight() - m_recCurFrame.top;
947 }
948 fl_DocSectionLayout * pDSL = pRun->getBlock()->getDocSectionLayout();
949 if(pDSL == NULL)
950 {
951 UT_DEBUGMSG(("No DocSectionLayout \n"));
952 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
953 return;
954 }
955
956 if(m_recCurFrame.width > pDSL->getActualColumnWidth())
957 {
958 m_recCurFrame.width = pDSL->getActualColumnWidth();
959 }
960 m_recOrigRight.left = xHigh > xLow ? xHigh : xLow;
961 m_recOrigRight.width = m_recCurFrame.left + m_recCurFrame.width > xHigh ?
962 m_recCurFrame.left + m_recCurFrame.width - xHigh : xHigh - (m_recCurFrame.left + m_recCurFrame.width);
963 m_recOrigRight.top = yy - pLineHigh->getHeight();
964 m_recOrigRight.height = pLineHigh->getHeight();
965
966 }
967 m_iLastX = x;
968 m_iLastY = y;
969 m_iInitialOffX = x - m_recCurFrame.left;
970 m_iInitialOffY = y - m_recCurFrame.top;
971 GR_Painter painter(getGraphics());
972 UT_RGBColor black(0,0,0);
973 UT_RGBColor trans(0,0,0,true);
974 m_pDragImage = painter.genImageFromRectangle(m_recCurFrame);
975 }
976
mouseCut(UT_sint32 x,UT_sint32 y)977 void FV_VisualDragText::mouseCut(UT_sint32 x, UT_sint32 y)
978 {
979 getImageFromSelection(x,y);
980 bool bPasteTableCol = (m_pView->getSelectionMode() == FV_SelectionMode_TableColumn);
981
982 // flag up on the document level that we are dragging with the mouse
983 // (in revisions mode the PT needs to be able to make a distinction between normal
984 // cut/delete and the mouse cut)
985 m_pView->getDocument()->setVDNDinProgress(true);
986
987 FV_ViewDoubleBuffering dblBuffObj(m_pView, true, true);
988 dblBuffObj.beginDoubleBuffering();
989
990 if(bPasteTableCol)
991 {
992 m_pView->cmdCut();
993 }
994 else
995 {
996 PT_DocPosition pos1 = m_pView->getSelectionAnchor();
997 PT_DocPosition pos2 = m_pView->getPoint();
998 if(pos1 > pos2)
999 {
1000 pos2 = m_pView->getSelectionAnchor();
1001 pos1 = m_pView->getPoint();
1002 }
1003 if(m_bSelectedRow)
1004 {
1005 m_pView->copyToLocal(pos1,pos2);
1006 m_pView->cmdDeleteRow(pos1+2);
1007 m_pView->setSelectionMode(FV_SelectionMode_TableRow);
1008 }
1009 else
1010 {
1011 m_pView->copyToLocal(pos1,pos2);
1012 m_pView->cmdCharDelete(true,1);
1013 }
1014 }
1015 m_pView->getDocument()->setVDNDinProgress(false);
1016
1017 m_pView->updateScreen(false);
1018
1019 dblBuffObj.endDoubleBuffering();
1020
1021 drawImage();
1022 }
1023
1024
mouseCopy(UT_sint32 x,UT_sint32 y)1025 void FV_VisualDragText::mouseCopy(UT_sint32 x, UT_sint32 y)
1026 {
1027 getImageFromSelection(x,y);
1028 bool bPasteTableCol = (m_pView->getPrevSelectionMode() == FV_SelectionMode_TableColumn);
1029 if(!bPasteTableCol)
1030 {
1031 PT_DocPosition pos1 = m_pView->getSelectionAnchor();
1032 PT_DocPosition pos2 = m_pView->getPoint();
1033 if(pos1 > pos2)
1034 {
1035 pos2 = m_pView->getSelectionAnchor();
1036 pos1 = m_pView->getPoint();
1037 }
1038 m_pView->copyToLocal(pos1,pos2);
1039 }
1040 else
1041 {
1042 m_pView->cmdCopy();
1043 }
1044 m_pView->updateScreen(false);
1045 drawImage();
1046 m_iVisualDragMode= FV_VisualDrag_START_DRAGGING;
1047 m_bTextCut = false;
1048 m_bDoingCopy = true;
1049 m_pView->_resetSelection();
1050 }
1051
getPosFromXY(UT_sint32 x,UT_sint32 y)1052 PT_DocPosition FV_VisualDragText::getPosFromXY(UT_sint32 x, UT_sint32 y)
1053 {
1054 //
1055 // Convert this to a document position and paste!
1056 //
1057 x -= m_iInitialOffX;
1058 y -= m_iInitialOffY;
1059 y += getGraphics()->tlu(6); //Otherwise it's too easy to hit the line above
1060 x += m_recOrigLeft.width; // Add in offset
1061 PT_DocPosition posAtXY = m_pView->getDocPositionFromXY(x,y,false);
1062 xxx_UT_DEBUGMSG(("Point at x %d y %d is %d \n",x,y,posAtXY));
1063 return posAtXY;
1064 }
1065
1066 /*!
1067 * This method oborts the current visual drag.
1068 */
abortDrag(void)1069 void FV_VisualDragText::abortDrag(void)
1070 {
1071 if(m_pAutoScrollTimer != NULL)
1072 {
1073 m_pAutoScrollTimer->stop();
1074 DELETEP(m_pAutoScrollTimer);
1075 }
1076 m_bSelectedRow = false;
1077 bool bDidCopy = m_bDoingCopy;
1078 m_bDoingCopy = false;
1079 m_bNotDraggingImage = false;
1080 clearCursor();
1081 UT_DEBUGMSG(("Abort Drag! \n"));
1082 if(m_iVisualDragMode != FV_VisualDrag_DRAGGING)
1083 {
1084 //
1085 // we didn't actually drag anything. Just release the selection.
1086 //
1087 setMode(FV_VisualDrag_NOT_ACTIVE);
1088 return;
1089 }
1090 getGraphics()->setClipRect(&m_recCurFrame);
1091 m_pView->updateScreen(false);
1092 getGraphics()->setClipRect(NULL);
1093 setMode(FV_VisualDrag_NOT_ACTIVE);
1094 if(!bDidCopy)
1095 {
1096 m_pView->cmdUndo(1);
1097 }
1098 return;
1099 }
1100 /*!
1101 * x and y is the location in the document windows of the mouse in logical
1102 * units.
1103 */
mouseRelease(UT_sint32 x,UT_sint32 y)1104 void FV_VisualDragText::mouseRelease(UT_sint32 x, UT_sint32 y)
1105 {
1106 if(m_pAutoScrollTimer != NULL)
1107 {
1108 m_pAutoScrollTimer->stop();
1109 DELETEP(m_pAutoScrollTimer);
1110 }
1111 m_bDoingCopy = false;
1112 m_bNotDraggingImage = false;
1113 m_bSelectedRow = false;
1114 clearCursor();
1115 if(m_iVisualDragMode != FV_VisualDrag_DRAGGING)
1116 {
1117 //
1118 // we didn't actually drag anything. Just release the selection.
1119 //
1120 m_pView->warpInsPtToXY(x, y,true);
1121 return;
1122 }
1123
1124 FV_ViewDoubleBuffering dblBuffObj(m_pView, true, true);
1125 dblBuffObj.beginDoubleBuffering();
1126
1127 PT_DocPosition posAtXY = getPosFromXY(x,y);
1128 m_pView->setPoint(posAtXY);
1129 fl_BlockLayout * pCurB = m_pView->getCurrentBlock();
1130 if(pCurB)
1131 {
1132 fl_ContainerLayout * pCL = pCurB->myContainingLayout();
1133 if(pCL && pCL->getContainerType() == FL_CONTAINER_SHADOW)
1134 {
1135 m_pView->setHdrFtrEdit(static_cast<fl_HdrFtrShadow *>(pCL));
1136 }
1137 }
1138 getGraphics()->setClipRect(&m_recCurFrame);
1139 m_pView->updateScreen(false);
1140 getGraphics()->setClipRect(NULL);
1141 m_iVisualDragMode = FV_VisualDrag_NOT_ACTIVE;
1142 m_pView->getMouseContext(x,y);
1143 m_iInitialOffX = 0;
1144 m_iInitialOffY = 0;
1145 PT_DocPosition oldPoint = m_pView->getPoint();
1146 if(oldPoint < 2)
1147 {
1148 oldPoint = 2;
1149 }
1150 bool bInFrame = m_pView->isInFrame(oldPoint);
1151
1152 bool bPasteTableCol = (m_pView->getPrevSelectionMode() == FV_SelectionMode_TableColumn);
1153 if(!bPasteTableCol)
1154 {
1155 m_pView->pasteFromLocalTo(m_pView->getPoint());
1156 }
1157 else
1158 {
1159 m_pView->cmdPaste();
1160 }
1161
1162 dblBuffObj.endDoubleBuffering();
1163
1164 m_bSelectedRow = false;
1165 PT_DocPosition newPoint = m_pView->getPoint();
1166 DELETEP(m_pDragImage);
1167 if(m_bTextCut)
1168 {
1169 m_pView->getDocument()->endUserAtomicGlob(); // End the big undo block
1170 }
1171 if(m_pView->getDocument()->isEndFootnoteAtPos(newPoint))
1172 {
1173 newPoint++;
1174 }
1175 bool bFinalFrame = m_pView->isInFrame(newPoint) && !m_pView->getDocument()->isFrameAtPos(newPoint);
1176 bool bDoSelect = true;
1177 if(bInFrame && !bFinalFrame)
1178 {
1179 bDoSelect = false;
1180 }
1181
1182 if(bDoSelect)
1183 {
1184 if(!bPasteTableCol)
1185 {
1186 m_pView->cmdSelect(oldPoint,newPoint);
1187 }
1188 else
1189 {
1190 m_pView->cmdSelectColumn(newPoint);
1191 }
1192 }
1193 m_bTextCut = false;
1194 }
1195
drawImage(void)1196 void FV_VisualDragText::drawImage(void)
1197 {
1198 if(m_bNotDraggingImage)
1199 {
1200 GR_Graphics::Cursor cursor = GR_Graphics::GR_CURSOR_DRAGTEXT;
1201 if(isDoingCopy())
1202 {
1203 cursor = GR_Graphics::GR_CURSOR_COPYTEXT;
1204 }
1205 getGraphics()->setCursor(cursor);
1206 return;
1207 }
1208 if(m_pDragImage == NULL)
1209 {
1210 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
1211 return;
1212 }
1213 GR_Painter painter(getGraphics());
1214 if( m_recOrigLeft.width > 0 || m_recOrigRight.width>0 )
1215 {
1216 UT_Rect dest;
1217 dest.left = m_recCurFrame.left + m_recOrigLeft.width;
1218 dest.top = m_recCurFrame.top;
1219 dest.width = m_recCurFrame.width - m_recOrigLeft.width;
1220 dest.height = m_recOrigLeft.height;
1221 UT_Rect src;
1222 src.left = m_recOrigLeft.width;
1223 src.top = 0;
1224 src.height = m_recOrigLeft.height;
1225 src.width = dest.width;
1226 if((src.height > getGraphics()->tlu(2)) && (src.width >getGraphics()->tlu(2)) )
1227 {
1228 painter.fillRect(m_pDragImage,&src,&dest);
1229 }
1230 dest.left = m_recCurFrame.left;
1231 dest.top = m_recCurFrame.top + m_recOrigLeft.height ;
1232 dest.width = m_recCurFrame.width;
1233 dest.height = m_recCurFrame.height - m_recOrigLeft.height - m_recOrigRight.height;
1234 src.left = 0;
1235 src.top = m_recOrigLeft.height ;
1236 src.width = m_recCurFrame.width;
1237 src.height = dest.height;
1238 if(src.height > getGraphics()->tlu(2) && src.width >getGraphics()->tlu(2) )
1239 {
1240 painter.fillRect(m_pDragImage,&src,&dest);
1241 }
1242 dest.left = m_recCurFrame.left;
1243 dest.top = m_recCurFrame.top + m_recCurFrame.height - m_recOrigRight.height;
1244 dest.width = m_recCurFrame.width - m_recOrigRight.width;
1245 dest.height = m_recOrigRight.height;
1246 src.top = m_recCurFrame.height - m_recOrigRight.height;
1247 src.left = 0;
1248 src.width = m_recCurFrame.width - m_recOrigRight.width;
1249 src.height = m_recOrigRight.height;
1250 if((src.height > getGraphics()->tlu(2)) && (src.width >getGraphics()->tlu(2)) )
1251 {
1252 painter.fillRect(m_pDragImage,&src,&dest);
1253 }
1254 return;
1255 }
1256 painter.drawImage(m_pDragImage,m_recCurFrame.left,m_recCurFrame.top);
1257 }
1258