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 "fv_FrameEdit.h"
21 #include "fl_DocLayout.h"
22 #include "pd_Document.h"
23 #include "gr_DrawArgs.h"
24 #include "gr_Graphics.h"
25 #include "ut_units.h"
26 #include "ut_debugmsg.h"
27 #include "fl_BlockLayout.h"
28 #include "fp_Line.h"
29 #include "fp_Run.h"
30 #include "pf_Frag.h"
31 #include "pf_Frag_Strux.h"
32 #include "fp_FrameContainer.h"
33 #include "fv_View.h"
34 #include "ev_Mouse.h"
35 #include "xap_Frame.h"
36 #include "gr_Painter.h"
37 #include "xap_App.h"
38 #include "fv_ViewDoubleBuffering.h"
39 
FV_FrameEdit(FV_View * pView)40 FV_FrameEdit::FV_FrameEdit (FV_View * pView)
41 	: FV_Base (pView),
42 	  m_iFrameEditMode(FV_FrameEdit_NOT_ACTIVE),
43 	  m_pFrameLayout(NULL),
44 	  m_pFrameContainer(NULL),
45 	  m_iLastX(0),
46 	  m_iLastY(0),
47 	  m_iInitialDragX(0),
48 	  m_iInitialDragY(0),
49 	  m_bInitialClick(false),
50 	  m_pFrameImage(NULL),
51 	  m_pAutoScrollTimer(NULL),
52 	  m_iInitialFrameX(0),
53 	  m_iInitialFrameY(0),
54 	  m_sRelWidth(""),
55 	  m_sMinHeight(""),
56 	  m_sExpandHeight("")
57 {
58 	UT_ASSERT_HARMLESS(pView);
59 }
60 
~FV_FrameEdit()61 FV_FrameEdit::~FV_FrameEdit()
62 {
63 	DELETEP(m_pFrameImage);
64 	if(m_pAutoScrollTimer)
65 	{
66 		m_pAutoScrollTimer->stop();
67 		DELETEP(m_pAutoScrollTimer);
68 	}
69 }
70 
setPointInside(void)71 void FV_FrameEdit::setPointInside(void)
72 {
73   fl_FrameLayout * pFL = getFrameLayout();
74   if(pFL == NULL)
75   {
76     return;
77   }
78   PT_DocPosition pos = pFL->getPosition(true) + pFL->getLength()-1;
79   setMode(FV_FrameEdit_NOT_ACTIVE);
80   m_pView->_setPoint(pos);
81 }
82 
isActive(void) const83 bool FV_FrameEdit::isActive(void) const
84 {
85 	return (FV_FrameEdit_NOT_ACTIVE != m_iFrameEditMode);
86 }
87 
setMode(FV_FrameEditMode iEditMode)88 void FV_FrameEdit::setMode(FV_FrameEditMode iEditMode)
89 {
90     UT_DEBUGMSG(("Frame Edit mode set to %d \n",iEditMode));
91 	if(iEditMode == FV_FrameEdit_NOT_ACTIVE)
92 	{
93 		m_pFrameLayout = NULL;
94 		m_pFrameContainer = NULL;
95 		DELETEP(m_pFrameImage);
96 		m_recCurFrame.width = 0;
97 		m_recCurFrame.height = 0;
98 		setDragWhat( FV_DragNothing );
99 		m_iLastX = 0;
100 		m_iLastY = 0;
101 	}
102 	m_iFrameEditMode = iEditMode;
103 	if(getGraphics()  && iEditMode !=  FV_FrameEdit_NOT_ACTIVE)
104 	{
105 	        getGraphics()->allCarets()->disable();
106 		m_pView->m_countDisable++;
107 	}
108 }
109 
110 
111 static bool bScrollRunning = false;
112 static UT_Worker * s_pScroll = NULL;
113 static UT_sint32 iExtra = 0;
114 
_actuallyScroll(UT_Worker * pWorker)115 void FV_FrameEdit::_actuallyScroll(UT_Worker * pWorker)
116 {
117 	// this is a static callback method and does not have a 'this' pointer.
118 
119 	FV_FrameEdit * pFE = static_cast<FV_FrameEdit *>(pWorker->getInstanceData());
120 	UT_return_if_fail(pFE);
121 	if(pFE->getFrameEditMode() != FV_FrameEdit_DRAG_EXISTING)
122 	{
123 		if(pFE->m_pAutoScrollTimer)
124 			pFE->m_pAutoScrollTimer->stop();
125 		DELETEP(pFE->m_pAutoScrollTimer);
126 		iExtra = 0;
127 		s_pScroll->stop();
128 		delete s_pScroll;
129 		s_pScroll = NULL;
130 		bScrollRunning = false;
131 		return;
132 	}
133 	FV_View * pView = pFE->m_pView;
134 	UT_sint32 x = pFE->m_xLastMouse;
135 	UT_sint32 y = pFE->m_yLastMouse;
136 	bool bScrollDown = false;
137 	bool bScrollUp = false;
138 	bool bScrollLeft = false;
139 	bool bScrollRight = false;
140 	bool bStop = false;
141 	if(y<=0)
142 	{
143 	  if(pView->getYScrollOffset() <= 10)
144 	  {
145 	      pView->setYScrollOffset(0);
146 	      pView->updateScreen(false);
147 	      bStop = true;
148 	  }
149 	  else
150 	  {
151 	      bScrollUp = true;
152 	  }
153 	}
154 	else if( y >= pView->getWindowHeight())
155 	{
156 	  if((pView->getYScrollOffset()+pView->getWindowHeight()+10) >= pView->getLayout()->getHeight())
157 	  {
158 	      pView->setYScrollOffset(pView->getLayout()->getHeight() - pView->getWindowHeight());
159 	      pView->updateScreen(false);
160 	      bStop = true;
161 	      UT_DEBUGMSG(("!!!!!!!!!!!!PLLLLLLLLLEEEEAAAASSSEEEEE STOOPPP!!!! \n"));
162 	  }
163 	  else
164 	  {
165 		bScrollDown = true;
166 	  }
167 	}
168 	if(x <= 0)
169 	{
170 		bScrollLeft = true;
171 	}
172 	else if(x >= pView->getWindowWidth())
173 	{
174 		bScrollRight = true;
175 	}
176 	if(!bStop && (bScrollDown || bScrollUp || bScrollLeft || bScrollRight))
177 	{
178 		pFE->getGraphics()->setClipRect(&pFE->m_recCurFrame);
179 		pView->updateScreen(false);
180 		pFE->getGraphics()->setClipRect(NULL);
181 		UT_sint32 minScroll = pFE->getGraphics()->tlu(20);
182 		if(bScrollUp)
183 		{
184 		        UT_sint32 yscroll = abs(y);
185 			if(yscroll < minScroll)
186 			    yscroll = minScroll;
187 			pView->cmdScroll(AV_SCROLLCMD_LINEUP, static_cast<UT_uint32>( yscroll +iExtra));
188 		}
189 		else if(bScrollDown)
190 		{
191 		        UT_sint32 yscroll = y - pView->getWindowHeight();
192 			if(yscroll < minScroll)
193 			    yscroll = minScroll;
194 			pView->cmdScroll(AV_SCROLLCMD_LINEDOWN, static_cast<UT_uint32>(yscroll+iExtra));
195 		}
196 		if(bScrollLeft)
197 		{
198 			pView->cmdScroll(AV_SCROLLCMD_LINELEFT, static_cast<UT_uint32>(-x));
199 		}
200 		else if(bScrollRight)
201 		{
202 			pView->cmdScroll(AV_SCROLLCMD_LINERIGHT, static_cast<UT_uint32>(x -pView->getWindowWidth()));
203 		}
204 		pFE->drawFrame(true);
205 		iExtra = 0;
206 		return;
207 	}
208 	else
209 	{
210 		if(pFE->m_pAutoScrollTimer)
211 			pFE->m_pAutoScrollTimer->stop();
212 		DELETEP(pFE->m_pAutoScrollTimer);
213 
214 	}
215 	iExtra = 0;
216 	s_pScroll->stop();
217 	delete s_pScroll;
218 	s_pScroll = NULL;
219 	bScrollRunning = false;
220 }
221 
_autoScroll(UT_Worker * pWorker)222 void FV_FrameEdit::_autoScroll(UT_Worker * pWorker)
223 {
224 	UT_return_if_fail(pWorker);
225 	// this is a static callback method and does not have a 'this' pointer.
226 
227 	FV_FrameEdit * pFE = static_cast<FV_FrameEdit *>(pWorker->getInstanceData());
228 	UT_return_if_fail(pFE);
229 	if(bScrollRunning)
230 	{
231 	    if(iExtra < pFE->getGraphics()->tlu(600))
232 	      iExtra += pFE->getGraphics()->tlu(20);
233 	    UT_DEBUGMSG(("Dropping FrameEditautoscroll !!!!!!! \n"));
234 	    return;
235 	}
236 
237 	UT_DEBUGMSG(("_autoscroll started!! \n"));
238 	int inMode = UT_WorkerFactory::IDLE | UT_WorkerFactory::TIMER;
239 	//	int inMode = UT_WorkerFactory::TIMER;
240 	UT_WorkerFactory::ConstructMode outMode = UT_WorkerFactory::NONE;
241 	s_pScroll = UT_WorkerFactory::static_constructor (_actuallyScroll,pFE, inMode, outMode);
242 
243 	// If the worker is working on a timer instead of in the idle
244 	// time, set the frequency of the checks.
245 	if ( UT_WorkerFactory::TIMER == outMode )
246 	{
247 		// this is really a timer, so it's safe to static_cast it
248 		static_cast<UT_Timer*>(s_pScroll)->set(100);
249 	}
250 	bScrollRunning = true;
251 	iExtra = 0;
252 	s_pScroll->start();
253 }
254 
255 /*!
256  * Returns 0 if the frame has never been dragged at all.
257  * Returns 1 if the frame has been dragged a little bit
258  * Return 10 if the frame has been dragged a lot.
259  */
haveDragged(void) const260 UT_sint32 FV_FrameEdit::haveDragged(void) const
261 {
262 	if(!m_bFirstDragDone)
263 	{
264 		return 0;
265 	}
266 	if((abs(m_xLastMouse - m_iFirstEverX) + abs(m_yLastMouse - m_iFirstEverY)) <
267 		getGraphics()->tlu(3))
268 	{
269 	  UT_DEBUGMSG(("Not dragged enough - return 1 \n"));
270 		return 1;
271 	}
272 	return 10;
273 }
274 
_mouseDrag(UT_sint32 x,UT_sint32 y)275 void FV_FrameEdit::_mouseDrag(UT_sint32 x, UT_sint32 y)
276 {
277 	FV_ViewDoubleBuffering dblBuffObj(m_pView, false, false);
278 	dblBuffObj.beginDoubleBuffering();
279 
280 	UT_sint32 dx = 0;
281 	UT_sint32 dy = 0;
282 	UT_Rect expX(0,m_recCurFrame.top,0,m_recCurFrame.height);
283 	UT_Rect expY(m_recCurFrame.left,0,m_recCurFrame.width,0);
284 
285 	FV_Base::_doMouseDrag( x, y, dx, dy, expX, expY );
286 	if (getDragWhat()==FV_DragWhole)
287 	{
288 		UT_sint32 diffx = 0;
289 		UT_sint32 diffy = 0;
290 		UT_sint32 iext = getGraphics()->tlu(3);
291 
292 		bool bScrollDown = false;
293 		bool bScrollUp = false;
294 		bool bScrollLeft = false;
295 		bool bScrollRight = false;
296 		if(y<=0)
297 		{
298 		  if(m_pView->getYScrollOffset() <= 0)
299 		    {
300 		      m_pView->setYScrollOffset(0);
301 		      m_pView->updateScreen(false);
302 		      if(m_pAutoScrollTimer)
303 			m_pAutoScrollTimer->stop();
304 		      DELETEP(m_pAutoScrollTimer);
305 		    }
306 		  else
307 		    {
308 		      bScrollUp = true;
309 		    }
310 		}
311 		else if( y >= m_pView->getWindowHeight())
312 		{
313 		  if(m_pView->getYScrollOffset() >= m_pView->getLayout()->getHeight())
314 		  {
315 		      m_pView->setYScrollOffset(m_pView->getLayout()->getHeight());
316 		      m_pView->updateScreen(false);
317 		      if(m_pAutoScrollTimer)
318 			m_pAutoScrollTimer->stop();
319 		      DELETEP(m_pAutoScrollTimer);
320 		  }
321 		  else
322 		  {
323 		      bScrollDown = true;
324 		  }
325 		}
326 		if(x <= 0)
327 		{
328 			bScrollLeft = true;
329 		}
330 		else if(x >= m_pView->getWindowWidth())
331 		{
332 			bScrollRight = true;
333 		}
334 		if(bScrollDown || bScrollUp || bScrollLeft || bScrollRight)
335 		{
336 			if(m_pAutoScrollTimer != NULL)
337 			{
338 				return;
339 			}
340 			m_pAutoScrollTimer = UT_Timer::static_constructor(_autoScroll, this);
341 			m_pAutoScrollTimer->set(AUTO_SCROLL_MSECS);
342 			m_pAutoScrollTimer->start();
343 			return;
344 		}
345 		diffx = m_iLastX - x;
346 		diffy = m_iLastY - y;
347 		dx = -diffx;
348 		dy = - diffy;
349 		m_recCurFrame.left -= diffx;
350 		m_recCurFrame.top -= diffy;
351 		UT_DEBUGMSG(("Doing drag whole frame left %d top %d \n",m_recCurFrame.left, m_recCurFrame.top));
352 		if(dx < 0)
353 		{
354 			expX.left = m_recCurFrame.left+m_recCurFrame.width -iext;
355 			expX.width = -dx + 2*iext;
356 			if(dy > 0)
357 			{
358 				expX.top -=  iext;
359 				expX.height += dy + 2*iext;
360 			}
361 			else
362 			{
363 				expX.top -=  iext;
364 				expX.height += (-dy + 2*iext);
365 			}
366 		}
367 		else
368 		{
369 			expX.left = m_recCurFrame.left - dx - iext;
370 			expX.width = dx + 2*iext;
371 			if(dy > 0)
372 			{
373 				expX.top -=  iext;
374 				expX.height += dy + 2*iext;
375 			}
376 			else
377 			{
378 				expX.top -= iext;
379 				expX.height += (-dy + 2*iext);
380 			}
381 		}
382 		expY.left -= iext;
383 		expY.width += 2*iext;
384 		if(dy < 0)
385 		{
386 			expY.top = m_recCurFrame.top + m_recCurFrame.height -iext;
387 			expY.height = -dy + 2*iext;
388 		}
389 		else
390 		{
391 			expY.top = m_recCurFrame.top - dy - iext;
392 			expY.height = dy + 2*iext;
393 		}
394 	}
395 	_checkDimensions();
396 
397 	if(FV_FrameEdit_RESIZE_INSERT == m_iFrameEditMode)
398 	{
399 		xxx_UT_DEBUGMSG(("width after drag %d \n",m_recCurFrame.width));
400 	}
401 	else
402 	{
403 		if (FV_FrameEdit_RESIZE_EXISTING == m_iFrameEditMode)
404 		{
405 			UT_sint32 iW = m_recCurFrame.width;
406 			UT_sint32 iH = m_recCurFrame.height;
407 			m_pFrameLayout->localCollapse();
408 			m_pFrameLayout->setFrameWidth(iW);
409 			m_pFrameLayout->setFrameHeight(iH);
410 			m_pFrameContainer->_setWidth(iW);
411 			m_pFrameContainer->_setHeight(iH);
412 			m_pFrameLayout->miniFormat();
413 			m_pFrameLayout->getDocSectionLayout()->setNeedsSectionBreak(false,NULL);
414 		}
415 
416 		if (FV_FrameEdit_RESIZE_EXISTING == m_iFrameEditMode || FV_FrameEdit_DRAG_EXISTING == m_iFrameEditMode)
417 		{
418 			UT_sint32 newX = m_pFrameContainer->getFullX();
419 			UT_sint32 newY = m_pFrameContainer->getFullY();
420 			newX += dx;
421 			newY += dy;
422 			m_pFrameContainer->_setX(newX);
423 			m_pFrameContainer->_setY(newY);
424 			if(expX.width > 0)
425 			{
426 				getGraphics()->setClipRect(&expX);
427 				m_pView->updateScreen(false);
428 			}
429 			if(expY.height > 0)
430 			{
431 				getGraphics()->setClipRect(&expY);
432 				m_pView->updateScreen(false);
433 			}
434 			getGraphics()->setClipRect(NULL);
435 
436 			drawFrame(true);
437 		}
438 	}
439 	m_iLastX = x;
440 	m_iLastY = y;
441 }
442 
443 /*!
444  * This method finds the correct frame on the screen associated with the
445  * (x,y) point.
446  * It sets the FV_FrameEditMode and the FV_FrameEditDragWhat mode depending
447  * on which control is selected at the (x,y) position.
448  *
449  *        top left     top edge     top right
450  *             X----------X----------X
451  *             |                     |
452  *             |                     |
453  * left edge   X                     X right edge
454  *             |                     |
455  *             |                     |
456  *             X----------X----------X
457  *        Bot left    Bot edge    Bot right
458  *
459  * An (x,y) point that does not fall in a specified control sets drag
460  * whole frame mode.
461  *
462  * The method also sets the fl_FrameLayout and FP_FrameContainer pointers.
463  */
setDragType(UT_sint32 x,UT_sint32 y,bool bDrawFrame)464 void FV_FrameEdit::setDragType(UT_sint32 x, UT_sint32 y, bool bDrawFrame)
465 {
466 	xxx_UT_DEBUGMSG(("setDragType called frameEdit mode %d \n",m_iFrameEditMode));
467 	PT_DocPosition posAtXY = m_pView->getDocPositionFromXY(x,y,false);
468 	fp_FrameContainer * pFCon = NULL;
469 	fl_FrameLayout * pFL = NULL;
470   	fl_BlockLayout * pBL = NULL;
471 	if(getDoc()->isFrameAtPos(posAtXY))
472 	{
473 		fl_ContainerLayout* psfh = NULL;
474 		getDoc()->getStruxOfTypeFromPosition(m_pView->getLayout()->getLID(),posAtXY+1,
475 										   PTX_SectionFrame, &psfh);
476 		pFL = static_cast<fl_FrameLayout *>(psfh);
477 		UT_ASSERT(pFL->getContainerType() == FL_CONTAINER_FRAME);
478 		pFCon = static_cast<fp_FrameContainer *>(pFL->getFirstContainer());
479 		UT_ASSERT(pFCon->getContainerType() == FP_CONTAINER_FRAME);
480 	}
481 	else
482 	{
483 		pBL = m_pView->_findBlockAtPosition(posAtXY);
484 		UT_return_if_fail(pBL);
485 	}
486 	if(!isActive() && (pFCon == NULL))
487 	{
488 		m_iFrameEditMode = 	FV_FrameEdit_EXISTING_SELECTED;
489 		if(getGraphics())
490 		{
491 		      getGraphics()->allCarets()->disable();
492 		      m_pView->m_countDisable++;
493 		}
494 		fl_ContainerLayout * pCL = pBL->myContainingLayout();
495 		while(pCL && (pCL->getContainerType() != FL_CONTAINER_FRAME) && (pCL->getContainerType() != FL_CONTAINER_DOCSECTION))
496 		{
497 			pCL = pCL->myContainingLayout();
498 		}
499 		UT_return_if_fail(pCL);
500 		if(pCL->getContainerType() != FL_CONTAINER_FRAME)
501 		{
502 			return;
503 		}
504 		m_pFrameLayout = static_cast<fl_FrameLayout *>(pCL);
505 		UT_ASSERT(m_pFrameLayout->getContainerType() == FL_CONTAINER_FRAME);
506 		m_pFrameContainer = static_cast<fp_FrameContainer *>(m_pFrameLayout->getFirstContainer());
507 		UT_ASSERT(m_pFrameContainer);
508 		if(bDrawFrame)
509 		{
510 			drawFrame(true);
511 		}
512 		m_iLastX = x;
513 		m_iLastY = y;
514 		setDragWhat( FV_DragWhole );
515 		return;
516 	}
517 	if(!isActive())
518 	{
519 		m_iFrameEditMode = 	FV_FrameEdit_EXISTING_SELECTED;
520 		if(getGraphics())
521 		{
522 		      getGraphics()->allCarets()->disable();
523 		      m_pView->m_countDisable++;
524 		}
525 		m_pFrameLayout = pFL;
526 		UT_ASSERT(m_pFrameLayout->getContainerType() == FL_CONTAINER_FRAME);
527 		m_pFrameContainer = pFCon;
528 		UT_ASSERT(m_pFrameContainer);
529 		if(bDrawFrame)
530 		{
531 			drawFrame(true);
532 		}
533 		m_iLastX = x;
534 		m_iLastY = y;
535 		setDragWhat( FV_DragWhole );
536 		return;
537 	}
538 	//
539 	// OK find the coordinates of the frame.
540 	//
541 	UT_sint32 xPage,yPage;
542 	UT_sint32 xClick, yClick;
543 	fp_Page* pPage = m_pView->_getPageForXY(x, y, xClick, yClick);
544 	m_pView->getPageScreenOffsets(pPage,xPage,yPage);
545 	if(m_iFrameEditMode == FV_FrameEdit_EXISTING_SELECTED)
546 	{
547 		pFCon = m_pFrameContainer;
548 		pFL = m_pFrameLayout;
549 	}
550 	else
551 	{
552 		if(pBL)
553 		{
554 			pFL = static_cast<fl_FrameLayout *>(pBL->myContainingLayout());
555 			pFCon = static_cast<fp_FrameContainer *>(pFL->getFirstContainer());
556 		}
557 		else
558 		{
559 			UT_ASSERT(pFL);
560 			UT_ASSERT(pFCon);
561 		}
562 	}
563 	UT_return_if_fail(pFCon);
564 	UT_sint32 ires = getGraphics()->tlu(FRAME_HANDLE_SIZE); // 6 pixels wide hit area
565 	UT_sint32 iLeft = xPage + pFCon->getFullX();
566 	UT_sint32 iRight = xPage + pFCon->getFullX() + pFCon->getFullWidth();
567 	UT_sint32 iTop = yPage + pFCon->getFullY();
568 	UT_sint32 iBot = yPage + pFCon->getFullY() + pFCon->getFullHeight();
569 	bool bX = (iLeft - ires < x) && (x < iRight + ires);
570 	bool bY = (iTop - ires < y) && (iBot + ires > y);
571 	bool bLeft = (iLeft - ires < x) && (x  < iLeft + ires);
572 	bool bRight = (iRight - ires < x) && (x < iRight + ires);
573 	bool bTop = (iTop - ires < y) && (y < iTop + ires);
574 	bool bBot = (iBot - ires < y) && (y < iBot + ires);
575 //
576 // top left
577 //
578 	if((iLeft < x) && (x < iLeft + ires) && (iTop < y) && (y < iTop + ires))
579 	{
580 		setDragWhat( FV_DragTopLeftCorner );
581 	}
582 //
583 // top Right
584 //
585 	else if((iRight - ires < x) && (x < iRight) && (iTop < y) && (y < iTop + ires))
586 	{
587 		setDragWhat( FV_DragTopRightCorner );
588 	}
589 //
590 // bot left
591 //
592 	else if((iLeft < x) && (x < iLeft + ires) && (iBot > y) && (y > iBot - ires))
593 	{
594 		setDragWhat( FV_DragBotLeftCorner );
595 	}
596 //
597 // Bot Right
598 //
599 	else if((iRight - ires < x) && (x < iRight) && (iBot > y) && (y > iBot - ires))
600 	{
601 		setDragWhat( FV_DragBotRightCorner );
602 	}
603 //
604 // top Edge
605 //
606 	else if( bX && bTop)
607 	{
608 		setDragWhat( FV_DragTopEdge );
609 	}
610 //
611 // left Edge
612 //
613 	else if(bLeft && bY)
614 	{
615 		setDragWhat( FV_DragLeftEdge );
616 	}
617 //
618 // right Edge
619 //
620 	else if(bRight && bY)
621 	{
622 		setDragWhat( FV_DragRightEdge );
623 	}
624 //
625 // bot Edge
626 //
627 	else if(bBot && bX)
628 	{
629 		setDragWhat( FV_DragBotEdge );
630 	}
631 	else
632 	{
633 		if( bX && bY)
634 		{
635 			setDragWhat( FV_DragWhole );
636 			xxx_UT_DEBUGMSG(("Dragging Whole Frame \n"));
637 		}
638 		else
639 		{
640 			setDragWhat( FV_DragNothing );
641 			return;
642 		}
643 	}
644 	if(bDrawFrame && (m_recCurFrame.width > 0) && (m_recCurFrame.height >0))
645 	{
646 		drawFrame(true);
647 	}
648 	const PP_AttrProp * pAP = NULL;
649 	pFL->getAP(pAP);
650 	const char * pszPercentWidth = NULL;
651 	const char * pszMinHeight = NULL;
652 	const char * pszExpandHeight = NULL;
653 	if(pAP && pAP->getProperty("frame-rel-width",pszPercentWidth))
654 	{
655 		if(pszPercentWidth)
656 		{
657 		     m_sRelWidth = pszPercentWidth;
658 		}
659 	}
660 	if(pAP && pAP->getProperty("frame-min-height",pszMinHeight))
661 	{
662 		if(pszMinHeight)
663 		{
664 		     m_sMinHeight = pszMinHeight;
665 		}
666 	}
667 	if(pAP && pAP->getProperty("frame-expand-height",pszExpandHeight))
668 	{
669 	        m_sExpandHeight = pszExpandHeight;
670 	}
671 	m_recCurFrame.left = iLeft;
672 	m_recCurFrame.top = iTop;
673 	m_recCurFrame.width = (iRight - iLeft);
674 	m_recCurFrame.height = (iBot - iTop);
675 	m_iLastX = x;
676 	m_iLastY = y;
677 	m_iInitialDragX = iLeft;
678 	m_iInitialDragY = iTop;
679 
680 	xxx_UT_DEBUGMSG(("Initial width %d \n",m_recCurFrame.width));
681 	xxx_UT_DEBUGMSG((" Dragging What %d \n",getDragWhat()));
682 	m_pView->setCursorToContext();
683 	if(getGraphics())
684 	{
685 	    getGraphics()->allCarets()->disable();
686 	    m_pView->m_countDisable++;
687 	}
688 }
689 
690 /*!
691  * This method responds to a mouse click and decides what to do with it.
692  */
mouseLeftPress(UT_sint32 x,UT_sint32 y)693 void FV_FrameEdit::mouseLeftPress(UT_sint32 x, UT_sint32 y)
694 {
695 	m_bFirstDragDone = false;
696 	UT_DEBUGMSG(("Mouse Left Press \n"));
697 	m_pView->_clearSelection();
698 	if(!isActive())
699 	{
700 		setDragType(x,y,true);
701 		UT_DEBUGMSG(("Was not active now %d FrameLayout %p \n",getFrameEditMode(),getFrameLayout()));
702 		return;
703 	}
704 //
705 // Find the type of drag we should do.
706 //
707 	if(FV_FrameEdit_EXISTING_SELECTED == m_iFrameEditMode )
708 	{
709 		setDragType(x,y,true);
710 		UT_DEBUGMSG(("Was Existing Selected now %d \n",getFrameEditMode()));
711 		if(FV_DragNothing == getDragWhat())
712 		{
713 			m_bFirstDragDone = false;
714 			m_iFrameEditMode = FV_FrameEdit_NOT_ACTIVE;
715 			drawFrame(false);
716 			if(m_pFrameContainer && m_pFrameLayout)
717 			{
718 			  if(m_pFrameLayout->getFrameType() > FL_FRAME_TEXTBOX_TYPE)
719 			  {
720 			    if(m_pFrameContainer->isTightWrapped())
721 			    {
722 			      //			      m_pFrameContainer->clearScreen();
723 			      m_pView->updateScreen(false);
724 			    }
725 			  }
726 			}
727 			m_pFrameLayout = NULL;
728 			m_pFrameContainer = NULL;
729 			DELETEP(m_pFrameImage);
730 			XAP_Frame * pFrame = static_cast<XAP_Frame*>(m_pView->getParentData());
731 			if(pFrame)
732 			{
733 				EV_Mouse * pMouse = pFrame->getMouse();
734 				if(pMouse)
735 				{
736 					pMouse->clearMouseContext();
737 				}
738 			}
739 			m_pView->m_prevMouseContext = EV_EMC_TEXT;
740 			m_pView->setCursorToContext();
741 			m_recCurFrame.width = 0;
742 			m_recCurFrame.height = 0;
743 			setDragWhat( FV_DragNothing );
744 			m_iLastX = 0;
745 			m_iLastY = 0;
746 			while(m_iGlobCount > 0)
747 				_endGlob();
748 			m_pView->warpInsPtToXY(x,y,true);
749 		}
750 		else
751 		{
752 			if( getDragWhat() != FV_DragWhole)
753 			{
754 				m_iFrameEditMode = FV_FrameEdit_RESIZE_EXISTING;
755 			}
756 			else
757 			{
758 				m_iFrameEditMode = FV_FrameEdit_DRAG_EXISTING;
759 				m_iInitialDragX = m_recCurFrame.left;
760 				m_iInitialDragY = m_recCurFrame.top;
761 				m_iInitialFrameX = m_pFrameContainer->getFullX();
762 				m_iInitialFrameY = m_pFrameContainer->getFullY();
763 			}
764 			if(getGraphics())
765 			{
766 			        getGraphics()->allCarets()->disable();
767 			        m_pView->m_countDisable++;
768 			}
769 		}
770 		return;
771 	}
772 //
773 // We're waiting for the first click to interactively enter the initial
774 // frame size.
775 //
776 	if(	FV_FrameEdit_WAIT_FOR_FIRST_CLICK_INSERT == m_iFrameEditMode )
777 	{
778 //
779 // Draw a marker at the current position
780 //
781 //
782 // Now insert a text box
783 //
784 		UT_sint32 iCursorOff = getGraphics()->tlu(8);
785 		UT_sint32 origX = x + iCursorOff;
786 		UT_sint32 origY = y + iCursorOff;
787 		UT_sint32 iSize = getGraphics()->tlu(32);
788 		m_recCurFrame.left = origX - iSize;
789 		m_recCurFrame.top = origY - iSize;
790 		m_recCurFrame.width = iSize;
791 		m_recCurFrame.height = iSize;
792 		m_iFrameEditMode = FV_FrameEdit_RESIZE_INSERT;
793 		_beginGlob();
794 //		mouseRelease(x,y);
795 		mouseRelease(origX,origY);
796 		m_iFrameEditMode = FV_FrameEdit_RESIZE_EXISTING;
797 		m_iLastX = x;
798 		m_iLastY = y;
799 		m_iInitialDragX = m_recCurFrame.left;
800 		m_iInitialDragY = m_recCurFrame.top;
801 		setDragWhat( FV_DragBotRightCorner );
802 		m_bFirstDragDone = false;
803 		m_bInitialClick = true;
804 		if(getGraphics())
805 		{
806 		      getGraphics()->allCarets()->disable();
807 		      m_pView->m_countDisable++;
808 		}
809 		getGraphics()->setCursor(GR_Graphics::GR_CURSOR_IMAGESIZE_SE);
810 	}
811 }
812 
isImageWrapper(void) const813 bool FV_FrameEdit::isImageWrapper(void) const
814 {
815         if(m_pFrameLayout == NULL)
816 	{
817 	        return false;
818 	}
819 	if(m_pFrameLayout->getFrameType() == FL_FRAME_WRAPPER_IMAGE)
820 	{
821 	        return true;
822 	}
823 	return false;
824 }
825 
getFrameStrings(UT_sint32 x,UT_sint32 y,fv_FrameStrings & FrameStrings,fl_BlockLayout ** pCloseBL,fp_Page ** ppPage)826 bool FV_FrameEdit::getFrameStrings(UT_sint32 x, UT_sint32 y,
827 				   fv_FrameStrings & FrameStrings,
828 				   fl_BlockLayout ** pCloseBL,
829 				   fp_Page ** ppPage)
830 {
831 //
832 // Find the block that contains (x,y). We'll insert the frame after
833 // this block in PT and position it on the page relative to this block.
834 //
835 //
836 // X and y are the (x,y) coords of the frame on the screen.
837 //
838                 PT_DocPosition posAtXY = 0;
839 		posAtXY = m_pView->getDocPositionFromXY(x,y,true);
840 		fl_BlockLayout * pBL = NULL;
841 		fp_Run * pRun = NULL;
842 		fp_Line * pLine = NULL;
843 		UT_sint32 x1,x2,y1,y2;
844 		UT_uint32 height;
845 		bool bEOL=false;
846 		bool bDir=false;
847 		m_pView->_findPositionCoords(posAtXY,bEOL,x1,y1,x2,y2,height,bDir,&pBL,&pRun);
848 		xxx_UT_DEBUGMSG((" Requested y %d frameEdit y1= %d y2= %d \n",y,y1,y2));
849 		fp_Run * pRunOrig = pRun;
850 		if((pBL == NULL) || (pRun == NULL))
851 		{
852 			return false;
853 		}
854 		fl_BlockLayout * pPrevBL = pBL;
855 		while(pBL && pBL->myContainingLayout() &&
856 		((pBL->myContainingLayout()->getContainerType() == FL_CONTAINER_ENDNOTE) ||
857 		(pBL->myContainingLayout()->getContainerType() == FL_CONTAINER_FOOTNOTE) ||
858 		(pBL->myContainingLayout()->getContainerType() == FL_CONTAINER_TOC) ||
859 		(pBL->myContainingLayout()->getContainerType() == FL_CONTAINER_FRAME) ||
860 		(pBL->myContainingLayout()->getContainerType() == FL_CONTAINER_CELL) ||
861 		(pBL->myContainingLayout()->getContainerType() == FL_CONTAINER_SHADOW) ||
862 		(pBL->myContainingLayout()->getContainerType() == FL_CONTAINER_HDRFTR)))
863 		{
864 		    UT_DEBUGMSG(("Skipping Block %p \n",pBL));
865 		    pPrevBL = pBL;
866 		    pBL = pBL->getPrevBlockInDocument();
867 		}
868 		if(pBL == NULL)
869 		{
870 		     pBL = pPrevBL;
871 		}
872 		pLine = pRun->getLine();
873 		if(pLine == NULL)
874 		{
875 			return false;
876 		}
877 		UT_ASSERT(pBL->myContainingLayout() && (pBL->myContainingLayout()->getContainerType() != FL_CONTAINER_HDRFTR)
878 			  && (pBL->myContainingLayout()->getContainerType() != FL_CONTAINER_SHADOW));
879 		*pCloseBL = pBL;
880 		posAtXY = pBL->getPosition();
881 
882 		// don't let widths and heights be too big
883 
884 		double dWidth = static_cast<double>(m_recCurFrame.width)/static_cast<double>(UT_LAYOUT_RESOLUTION);
885 		double dHeight = static_cast<double>(m_recCurFrame.height)/static_cast<double>(UT_LAYOUT_RESOLUTION);
886 		if(m_pView->getPageSize().Width(DIM_IN) < dWidth)
887 		{
888 		    dWidth = m_pView->getPageSize().Width(DIM_IN)*0.99;
889 		    m_recCurFrame.width = static_cast<UT_sint32>(dWidth*UT_LAYOUT_RESOLUTION);
890 		}
891 		if(m_pView->getPageSize().Height(DIM_IN) < dHeight)
892 		{
893 		    dHeight = m_pView->getPageSize().Height(DIM_IN)*0.99;
894 		    m_recCurFrame.height = static_cast<UT_sint32>(dHeight*UT_LAYOUT_RESOLUTION);
895 		}
896 //
897 // Need this for offset to column
898 //
899 		UT_return_val_if_fail(pBL->getFirstRun(),false);
900 		UT_return_val_if_fail(pBL->getFirstRun()->getLine(),false);
901 		UT_return_val_if_fail(pBL->getFirstRun()->getLine()->getColumn(),false);
902 		fp_Container * pCol = pRunOrig->getLine()->getColumn();
903 		UT_ASSERT(pCol->getContainerType() == FP_CONTAINER_COLUMN);
904 //
905 // Find the screen coords of pCol and substract then from x,y
906 //
907 		UT_sint32 iColx = 0;
908 		UT_sint32 iColy = 0;
909 		fp_Page * pPage = pCol->getPage();
910 		if(!pPage)
911 		{
912 		    return false;
913 		}
914 		else
915 		{
916 		    pPage->getScreenOffsets(pCol,iColx,iColy);
917 		}
918 		UT_sint32 xp=0;
919 		UT_sint32 yp= 0;
920 		m_pView->getPageScreenOffsets(pPage,xp,yp);
921 		UT_sint32 finalColx = x - iColx;
922 		if(finalColx + iColx - xp < 0)
923 		{
924 			x += -finalColx -iColx +xp;
925 		}
926 		else if(pPage && (finalColx + iColx + m_recCurFrame.width - xp > pPage->getWidth()))
927 		{
928 		    x = pPage->getWidth() - m_recCurFrame.width;
929 		}
930 		finalColx = x - iColx;
931 
932 		UT_sint32 finalColy = y - iColy;
933 		if(finalColy + iColy - yp < 0 )
934 		{
935 			y += -iColy - finalColy +yp;
936 		}
937 		else if (pPage && (finalColy + iColy - yp+  m_recCurFrame.height  > pPage->getHeight()))
938 		{
939 		        y = pPage->getHeight() - m_recCurFrame.height;
940 		}
941 		finalColy = y - iColy;
942 
943 		double xPos = static_cast<double>(finalColx)/static_cast<double>(UT_LAYOUT_RESOLUTION);
944 		double yPos = static_cast<double>(finalColy)/static_cast<double>(UT_LAYOUT_RESOLUTION);
945 		FrameStrings.sColXpos = UT_formatDimensionedValue(xPos,"in", NULL);
946 		FrameStrings.sColYpos = UT_formatDimensionedValue(yPos,"in", NULL);
947 		//
948 		// OK calculate relative to page now
949 		//
950 		xPos += static_cast<double>(pCol->getX())/static_cast<double>(UT_LAYOUT_RESOLUTION);
951 		yPos += static_cast<double>(pCol->getY())/static_cast<double>(UT_LAYOUT_RESOLUTION);
952 		FrameStrings.sPageXpos = UT_formatDimensionedValue(xPos,"in", NULL);
953 		FrameStrings.sPageYpos = UT_formatDimensionedValue(yPos,"in", NULL);
954 
955 //
956 // Find the screen coords of pLine, then work out the offset to the (x,y)
957 // point. After that workout the offset to the first line of the block.
958 //
959 //
960 		UT_sint32 xBlockOff =0;
961 		UT_sint32 yBlockOff = 0;
962 		UT_DebugOnly<bool> bValid = false;
963 		bValid = pBL->getXYOffsetToLine(xBlockOff,yBlockOff,pLine);
964 		UT_ASSERT(bValid);
965 		fp_Line * pFirstL = static_cast<fp_Line *>(pBL->getFirstContainer());
966 		UT_sint32 xFirst,yFirst;
967 		pFirstL->getScreenOffsets(pFirstL->getFirstRun(),xFirst,yFirst);
968 		xxx_UT_DEBUGMSG(("First line x  %d y %d \n",xFirst,yFirst));
969 		xxx_UT_DEBUGMSG(("xBlockOffset %d yBlockOffset %d \n",xBlockOff,yBlockOff));
970 		UT_sint32 xLineOff = 0;
971 		UT_sint32 yLineOff = 0;
972 		fp_VerticalContainer * pVCon = static_cast<fp_VerticalContainer *>(pLine->getContainer());
973 		pVCon->getOffsets(pLine,xLineOff,yLineOff);
974 		xLineOff -= pLine->getX();
975 		xxx_UT_DEBUGMSG(("Closest Line yLineoff %d \n",yLineOff));
976 
977 // OK correct for page offsets
978 		pPage = pVCon->getPage();
979 		if(pPage == NULL)
980 		{
981 			return false;
982 		}
983 		m_pView->getPageScreenOffsets(pPage,xp,yp);
984 		xLineOff = x -xp - xLineOff;
985 //		yLineOff = y + pRun->getY() - yLineOff  + yBlockOff;
986 		yLineOff = y - yp - yLineOff + yBlockOff;
987 		UT_DEBUGMSG(("fv_FrameEdit: (x,y) %d %d xLineOff %d yLineOff %d \n",x,y,xLineOff,yLineOff));
988 //
989 // The sXpos and sYpos values are the numbers that need to be added from the
990 // top left corner of thefirst line of the block to reach the top left
991 // corner of the frame. We now have these in layout units. Convert to inches
992 // now
993 //
994 		xPos = static_cast<double>(xLineOff)/static_cast<double>(UT_LAYOUT_RESOLUTION);
995 		yPos = static_cast<double>(yLineOff)/static_cast<double>(UT_LAYOUT_RESOLUTION);
996 		FrameStrings.sXpos = UT_formatDimensionedValue(xPos,"in", NULL);
997 		FrameStrings.sYpos = UT_formatDimensionedValue(yPos,"in", NULL);
998 		FrameStrings.sWidth = UT_formatDimensionedValue(dWidth,"in", NULL);
999 		FrameStrings.sHeight = UT_formatDimensionedValue(dHeight,"in", NULL);
1000 		*ppPage = pPage;
1001 		UT_sint32 iPage = getView()->getLayout()->findPage(pPage);
1002 		UT_String_sprintf(FrameStrings.sPrefPage,"%d",iPage);
1003 		fp_Column * pColumn = static_cast<fp_Column *>(pCol);
1004 		UT_sint32 iColumn = pColumn->getColumnIndex();
1005 		UT_String_sprintf(FrameStrings.sPrefColumn,"%d",iColumn);
1006 
1007 		return true;
1008 }
1009 
1010 //
1011 // Abort the current drag
1012 //
1013 //
abortDrag(void)1014 void FV_FrameEdit::abortDrag(void)
1015 {
1016   FV_ViewDoubleBuffering dblBuffObj(m_pView, true, true);
1017   dblBuffObj.beginDoubleBuffering();
1018 
1019 
1020   UT_DEBUGMSG(("Doing Abort Drag \n"));
1021   m_xLastMouse = m_iFirstEverX;
1022   m_yLastMouse = m_iFirstEverY;
1023   mouseRelease(m_iInitialDragX,m_iInitialDragY);
1024   getView()->updateScreen(false);
1025 }
1026 
mouseRelease(UT_sint32 x,UT_sint32 y)1027 void FV_FrameEdit::mouseRelease(UT_sint32 x, UT_sint32 y)
1028 {
1029 //
1030 // If we've just selected the frame, ignore this event.
1031 //
1032 
1033 	FV_ViewDoubleBuffering dblBuffObj(m_pView, true, true);
1034 	dblBuffObj.beginDoubleBuffering();
1035 
1036 	UT_DEBUGMSG(("Doing mouse release now! Mode %d \n", getFrameEditMode()));
1037 	if(FV_FrameEdit_EXISTING_SELECTED == m_iFrameEditMode)
1038 	{
1039 		UT_DEBUGMSG(("Existing Frame selected now released button isActive() %d \n",isActive()));
1040 		return;
1041 	}
1042 	if(m_pAutoScrollTimer != NULL)
1043 	{
1044 		m_pAutoScrollTimer->stop();
1045 		DELETEP(m_pAutoScrollTimer);
1046 	}
1047 
1048 	PT_DocPosition posAtXY = 0;
1049 
1050 	if(m_iFrameEditMode == 	FV_FrameEdit_RESIZE_INSERT)
1051 	{
1052 		// Signal PieceTable Change
1053 		m_pView->_saveAndNotifyPieceTableChange();
1054 
1055 	// Turn off list updates
1056 
1057 		getDoc()->disableListUpdates();
1058 		_beginGlob();
1059 
1060 		fv_FrameStrings FrameStrings;
1061 		fl_BlockLayout * pCloseBL = NULL;
1062 		fp_Page * pPage = NULL;
1063 		getFrameStrings(m_recCurFrame.left,m_recCurFrame.top,FrameStrings,&pCloseBL,&pPage);
1064 		pf_Frag_Strux * pfFrame = NULL;
1065 		// WARNING: Will need to change this to accomodate variable styles without constantly resetting to solid.
1066 		//				 Recommend to do whatever is done for thickness, which must also have a default set but not
1067 		//				 reverted to on every change.
1068 		// TODO: if(pAP->getProperty("*-thickness", somePropHolder)) sLeftThickness = gchar_strdup(somePropHolder); else sLeftThickness = "1px";
1069 		const gchar * props[48] = {"frame-type","textbox",
1070 					      "wrap-mode","wrapped-both",
1071 					      "position-to","column-above-text",
1072 					      "xpos",FrameStrings.sXpos.c_str(),
1073 					      "ypos",FrameStrings.sYpos.c_str(),
1074 					      "frame-width",FrameStrings.sWidth.c_str(),
1075 					      "frame-height",FrameStrings.sHeight.c_str(),
1076 					      "frame-col-xpos",FrameStrings.sColXpos.c_str(),
1077 					      "frame-col-ypos",FrameStrings.sColYpos.c_str(),
1078 					      "frame-page-xpos",FrameStrings.sPageXpos.c_str(),
1079 					      "frame-page-ypos",FrameStrings.sPageYpos.c_str(),
1080 					   "frame-pref-page",FrameStrings.sPrefPage.c_str(),
1081 					   "frame-pref-column",FrameStrings.sPrefColumn.c_str(),
1082 					      "background-color", "ffffff",
1083 						  "left-style","1",
1084 						  "right-style","1",
1085 						  "top-style","1",
1086 						  "bot-style","1",
1087 						  "bg-style","1",
1088 					   "tight-wrap","0",
1089 					   "frame-rel-width",m_sRelWidth.c_str(),
1090 					   "frame-min-height",m_sMinHeight.c_str(),
1091 					   "frame-expand-height",m_sExpandHeight.c_str(),
1092 					      NULL,NULL};
1093 //
1094 // This should place the the frame strux immediately after the block containing
1095 // position posXY.
1096 // It returns the Frag_Strux of the new frame.
1097 //
1098 		const PP_AttrProp* pBlockAP = NULL;
1099 		pCloseBL->getAP(pBlockAP);
1100 		posAtXY = pCloseBL->getPosition();
1101 		getDoc()->insertStrux(posAtXY,PTX_SectionFrame,NULL,props,&pfFrame);
1102 		PT_DocPosition posFrame = pfFrame->getPos();
1103 		PT_DocPosition posEOD= 0;
1104 		m_pView->getEditableBounds(true,posEOD);
1105 		getDoc()->insertStrux(posFrame+1,PTX_Block,NULL,pBlockAP->getProperties());
1106 		getDoc()->insertStrux(posFrame+2,PTX_EndFrame);
1107 		m_pView->insertParaBreakIfNeededAtPos(posFrame+3);
1108 
1109 // Place the insertion point in the Frame
1110 
1111 		m_pView->setPoint(posFrame+2);
1112 
1113 // Finish up with the usual stuff
1114 
1115 		m_pView->_generalUpdate();
1116 
1117 		_endGlob();
1118 
1119 
1120 	// restore updates and clean up dirty lists
1121 		getDoc()->enableListUpdates();
1122 		getDoc()->updateDirtyLists();
1123 
1124 	// Signal PieceTable Changes have finished
1125 		m_pView->_restorePieceTableState();
1126 		m_pView->notifyListeners(AV_CHG_HDRFTR);
1127 		m_pView->_fixInsertionPointCoords();
1128 		m_pView->_ensureInsertionPointOnScreen();
1129 
1130 //
1131 		m_iFrameEditMode = 	FV_FrameEdit_EXISTING_SELECTED;
1132 		if(getGraphics())
1133 		{
1134 		      getGraphics()->allCarets()->disable();
1135 		      m_pView->m_countDisable++;
1136 		}
1137 		fl_BlockLayout * pBL = m_pView->_findBlockAtPosition(posFrame+2);
1138 		fl_ContainerLayout * pCL = pBL->myContainingLayout();
1139 		while(pCL && (pCL->getContainerType() != FL_CONTAINER_FRAME) && (pCL->getContainerType() != FL_CONTAINER_DOCSECTION))
1140 		{
1141 			pCL = pCL->myContainingLayout();
1142 		}
1143 		UT_return_if_fail(pCL);
1144 		if(pCL->getContainerType() != FL_CONTAINER_FRAME)
1145 		{
1146 			return;
1147 		}
1148 		m_pFrameLayout = static_cast<fl_FrameLayout *>(pCL);
1149 		UT_ASSERT(m_pFrameLayout->getContainerType() == FL_CONTAINER_FRAME);
1150 		m_pFrameContainer = static_cast<fp_FrameContainer *>(m_pFrameLayout->getFirstContainer());
1151 		UT_ASSERT(m_pFrameContainer);
1152 		drawFrame(true);
1153 		m_bFirstDragDone = false;
1154 		return;
1155 	}
1156 
1157 // Do Resize and Drag of frame
1158 
1159 	else if((m_iFrameEditMode == FV_FrameEdit_RESIZE_EXISTING) ||
1160 			(m_iFrameEditMode == FV_FrameEdit_DRAG_EXISTING))
1161 	{
1162 		const PP_AttrProp* pSectionAP = NULL;
1163 		m_pFrameLayout->getAP(pSectionAP);
1164 
1165 //
1166 // If there was no drag, the user just clicked and released the left mouse
1167 // no need to change anything.
1168 //
1169 		if(haveDragged() < 10)
1170 		{
1171 			m_iFrameEditMode = FV_FrameEdit_NOT_ACTIVE;
1172 			setDragWhat( FV_DragNothing );
1173 			m_pFrameContainer->_setX(m_iInitialFrameX);
1174 			m_pFrameContainer->_setY(m_iInitialFrameY);
1175 			m_iInitialFrameX = 0;
1176 			m_iInitialFrameY = 0;
1177 			drawFrame(false);
1178 			m_pFrameLayout = NULL;
1179 			m_pFrameContainer = NULL;
1180 			DELETEP(m_pFrameImage);
1181 			XAP_Frame * pFrame = static_cast<XAP_Frame*>(m_pView->getParentData());
1182 			if(pFrame)
1183 			{
1184 				EV_Mouse * pMouse = pFrame->getMouse();
1185 				if(pMouse)
1186 				{
1187 					pMouse->clearMouseContext();
1188 				}
1189 			}
1190 			m_pView->m_prevMouseContext = EV_EMC_TEXT;
1191 			m_pView->setCursorToContext();
1192 			m_recCurFrame.width = 0;
1193 			m_recCurFrame.height = 0;
1194 			m_iLastX = 0;
1195 			m_iLastY = 0;
1196 			m_bFirstDragDone = false;
1197 			while(m_iGlobCount > 0)
1198 				_endGlob();
1199 			m_pView->warpInsPtToXY(x,y,true);
1200 			UT_DEBUGMSG(("Completed small drag \n"));
1201 			return;
1202 		}
1203 //
1204 // OK get the properties of the current frame, update them with the new
1205 // the position and size of this drag.
1206 //
1207 
1208 //  Frame Image
1209 
1210 		fv_FrameStrings FrameStrings;
1211 		fl_BlockLayout * pCloseBL = NULL;
1212 		fp_Page * pPage = NULL;
1213 		fl_FrameLayout *pFL = m_pFrameLayout;
1214 		getFrameStrings(m_recCurFrame.left,m_recCurFrame.top,FrameStrings,
1215 				&pCloseBL,&pPage);
1216 		posAtXY = pCloseBL->getPosition();
1217 
1218 		const gchar * props[] = {"xpos",FrameStrings.sXpos.c_str(),
1219 					 "ypos",FrameStrings.sYpos.c_str(),
1220 					 "frame-col-xpos",FrameStrings.sColXpos.c_str(),
1221 					 "frame-col-ypos",FrameStrings.sColYpos.c_str(),
1222 					 "frame-page-xpos",FrameStrings.sPageXpos.c_str(),
1223 					 "frame-page-ypos",FrameStrings.sPageYpos.c_str(),
1224 					 "frame-pref-page",FrameStrings.sPrefPage.c_str(),
1225 					 "frame-pref-column",FrameStrings.sPrefColumn.c_str(),
1226 					  "frame-width",FrameStrings.sWidth.c_str(),
1227 					 "frame-height",FrameStrings.sHeight.c_str(),
1228 					 NULL};
1229 		// Signal PieceTable Change
1230 		m_pView->_saveAndNotifyPieceTableChange();
1231 		getDoc()->disableListUpdates();
1232 		_beginGlob();
1233 
1234 		m_pView->_clearSelection();
1235 
1236 		if (pFL->getParentContainer() == pCloseBL)
1237 		{
1238 		    PT_DocPosition posStart = pFL->getPosition(true)+1;
1239 		    PT_DocPosition posEnd = posStart;
1240 		    UT_DebugOnly<bool> bRet = getDoc()->changeStruxFmt(PTC_AddFmt,posStart,posEnd,NULL,
1241 								       props,PTX_SectionFrame);
1242 		    UT_ASSERT(bRet);
1243 		}
1244 		else
1245 		{
1246 		    pFL = getLayout()->relocateFrame(pFL,pCloseBL,NULL,props);
1247 		}
1248 
1249         // Finish up with the usual stuff
1250 		m_pView->_generalUpdate();
1251 
1252 	// restore updates and clean up dirty lists
1253 		getDoc()->enableListUpdates();
1254 		getDoc()->updateDirtyLists();
1255 		m_pView->_restorePieceTableState();
1256 		PT_DocPosition posFrame = getDoc()->getStruxPosition(pFL->getStruxDocHandle());
1257 		m_pView->setPoint(posFrame+1);
1258 		bool bOK = true;
1259 		while(!m_pView->isPointLegal() && bOK)
1260 		{
1261 		    bOK = m_pView->_charMotion(true,1);
1262 		}
1263 		m_pView->notifyListeners(AV_CHG_HDRFTR);
1264 		m_pView->_fixInsertionPointCoords();
1265 //
1266 // If this was a drag following the initial click, wrap it in a
1267 // endUserAtomicGlob so it undo's in a single click.
1268 //
1269 		while(m_iGlobCount > 0)
1270 			_endGlob();
1271 
1272 		m_bInitialClick = false;
1273 //
1274 // Finish up by putting the editmode back to existing selected.
1275 //
1276 		m_pView->updateScreen(false);
1277 		m_pFrameLayout = pFL;
1278 		setMode(FV_FrameEdit_EXISTING_SELECTED);
1279 		if(getGraphics())
1280 		{
1281 		      getGraphics()->allCarets()->disable();
1282 		      m_pView->m_countDisable++;
1283 		}
1284 		if(m_pFrameLayout)
1285 			m_pFrameContainer = static_cast<fp_FrameContainer *>(m_pFrameLayout->getFirstContainer());
1286 		drawFrame(true);
1287 		m_bFirstDragDone = false;
1288 		// This must be done after painting because it will finish the cairo surface, see #13622
1289 		m_pView->_ensureInsertionPointOnScreen();
1290 	}
1291 	m_bFirstDragDone = false;
1292 }
1293 
1294 /*
1295  * Return the bytebuf of the image for this.
1296  */
getPNGImage(const UT_ByteBuf ** ppByteBuf)1297 const char * FV_FrameEdit::getPNGImage(const UT_ByteBuf ** ppByteBuf )
1298 {
1299 
1300 //  Frame Image
1301       const PP_AttrProp* pSectionAP = NULL;
1302       m_pFrameLayout->getAP(pSectionAP);
1303 
1304       const char * pszDataID = NULL;
1305       pSectionAP->getAttribute(PT_STRUX_IMAGE_DATAID, (const gchar *&)pszDataID);
1306       if(!pszDataID)
1307       {
1308 	  *ppByteBuf = NULL;
1309 	  return NULL;
1310       }
1311       m_pView->getDocument()->getDataItemDataByName(pszDataID,ppByteBuf,NULL,NULL);
1312       return pszDataID;
1313 }
1314 
1315 /*!
1316  * This method deletes the current selected frame
1317  */
deleteFrame(fl_FrameLayout * pFL)1318 void FV_FrameEdit::deleteFrame(fl_FrameLayout * pFL)
1319 {
1320 	if(m_pFrameLayout == NULL)
1321 	{
1322 	        m_pFrameLayout = pFL;
1323 		if(m_pFrameLayout == NULL)
1324 		{
1325 		  UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
1326 		  return;
1327 		}
1328 	}
1329 
1330 	FV_ViewDoubleBuffering dblBuffObj(m_pView, true, true);
1331 	dblBuffObj.beginDoubleBuffering();
1332 
1333 	PP_AttrProp * p_AttrProp_Before = NULL;
1334 
1335 	// Signal PieceTable Change
1336 	m_pView->_saveAndNotifyPieceTableChange();
1337 
1338 	// Turn off list updates
1339 
1340 	getDoc()->disableListUpdates();
1341 	_beginGlob();
1342 
1343 // Delete the frame
1344 
1345 	pf_Frag_Strux* sdhStart =  m_pFrameLayout->getStruxDocHandle();
1346 	pf_Frag_Strux* sdhEnd = NULL;
1347 	PT_DocPosition posStart = getDoc()->getStruxPosition(sdhStart);
1348 	getDoc()->getNextStruxOfType(sdhStart, PTX_EndFrame, &sdhEnd);
1349 	PT_DocPosition posEnd = getDoc()->getStruxPosition(sdhEnd)+1;
1350 	UT_uint32 iRealDeleteCount;
1351 
1352 	getDoc()->deleteSpan(posStart, posEnd, p_AttrProp_Before, iRealDeleteCount,true);
1353 
1354 	//special handling is required for delete in revisions mode
1355 	//where we have to move the insertion point
1356 	if(m_pView->isMarkRevisions())
1357 	{
1358 		UT_ASSERT( iRealDeleteCount <= posEnd - posStart + 1 );
1359 		m_pView->_charMotion(true,posEnd - posStart - iRealDeleteCount);
1360 	}
1361 
1362 // Finish up with the usual stuff
1363 
1364 	m_pView->_generalUpdate();
1365 
1366 	// restore updates and clean up dirty lists
1367 	getDoc()->enableListUpdates();
1368 	getDoc()->updateDirtyLists();
1369 
1370 	// Signal PieceTable Changes have finished
1371 	m_pView->_restorePieceTableState();
1372 	m_pView->notifyListeners(AV_CHG_HDRFTR);
1373 	m_pView->_fixInsertionPointCoords();
1374 	m_pView->_ensureInsertionPointOnScreen();
1375 	while(m_iGlobCount > 0)
1376 		_endGlob();
1377 
1378 // Clear all internal variables
1379 
1380 	m_pFrameLayout = NULL;
1381 	m_pFrameContainer = NULL;
1382 	DELETEP(m_pFrameImage);
1383 	m_recCurFrame.width = 0;
1384 	m_recCurFrame.height = 0;
1385 	setDragWhat( FV_DragNothing );
1386 	m_iLastX = 0;
1387 	m_iLastY = 0;
1388 
1389 	m_iFrameEditMode = FV_FrameEdit_NOT_ACTIVE;
1390 	m_bFirstDragDone = false;
1391 	m_pView->_setPoint(m_pView->getPoint());
1392 }
1393 
1394 /*!
1395  * Method to deal with mouse coordinates.
1396  */
mouseMotion(UT_sint32,UT_sint32)1397 FV_DragWhat FV_FrameEdit::mouseMotion(UT_sint32 /*x*/, UT_sint32 /*y*/)
1398 {
1399 	return getDragWhat();
1400 }
1401 
drawFrame(bool bWithHandles)1402 void FV_FrameEdit::drawFrame(bool bWithHandles)
1403 {
1404 	if(m_pFrameContainer == NULL)
1405 	{
1406 		UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
1407 		return;
1408 	}
1409 	fp_Page * pPage = m_pFrameContainer->getPage();
1410 	dg_DrawArgs da;
1411 	da.pG = getGraphics();
1412 	da.bDirtyRunsOnly = false;
1413 	UT_sint32 xPage,yPage;
1414 	m_pView->getPageScreenOffsets(pPage,xPage,yPage);
1415 	da.xoff = xPage + m_pFrameContainer->getX();
1416 	da.yoff = yPage + m_pFrameContainer->getY();
1417 	if((m_pFrameImage == NULL) || (getDragWhat() != FV_DragWhole) )
1418 	{
1419 //		m_pFrameContainer->clearScreen();
1420 		m_pFrameContainer->draw(&da);
1421 		if(bWithHandles)
1422 		{
1423 			m_pFrameContainer->drawHandles(&da);
1424 		}
1425 		if(getDragWhat() == FV_DragWhole)
1426 		{
1427 			GR_Painter painter (getGraphics());
1428 			if(m_pFrameLayout->getFrameType() == FL_FRAME_TEXTBOX_TYPE)
1429 			{
1430 			      m_pFrameImage = painter.genImageFromRectangle(m_recCurFrame);
1431 			}
1432 			else
1433 		        {
1434 			      UT_Rect rec = m_recCurFrame;
1435 			      rec.left = 0;
1436 			      rec.top = 0;
1437 				  UT_return_if_fail(m_pFrameLayout->getBackgroundImage());
1438 			      m_pFrameImage = m_pFrameLayout->getBackgroundImage()->createImageSegment(getGraphics(),rec);
1439 			}
1440 		}
1441 	}
1442 	else
1443 	{
1444 		GR_Painter painter(getGraphics());
1445 		m_pView->draw(&m_recCurFrame);
1446 		painter.drawImage(m_pFrameImage,m_recCurFrame.left,m_recCurFrame.top);
1447 	}
1448 }
1449