1 /* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */
2 
3 /* AbiWord
4  * Copyright (C) 2002 Dom Lachowicz, William Lachance and others
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301 USA.
20  */
21 
22 #include "ut_types.h"
23 #include "ap_Frame.h"
24 #include "xap_App.h"
25 
26 #include "ap_Features.h"
27 
28 #include "ap_FrameData.h"
29 #include "ap_Strings.h"
30 #include "fv_View.h"
31 #include "xav_View.h"
32 #include "xad_Document.h"
33 #include "pd_Document.h"
34 #include "xap_ViewListener.h"
35 #include "xap_Scrollbar_ViewListener.h"
36 #include "ap_TopRuler.h"
37 #include "ap_LeftRuler.h"
38 #include "ap_StatusBar.h"
39 #include "xap_Dlg_Zoom.h"
40 
41 /*****************************************************************/
42 
43 #define ENSUREP_C(p)		do { UT_ASSERT_HARMLESS(p); if (!p) goto Cleanup; } while (0)
44 
45 /*****************************************************************/
46 
setZoomPercentage(UT_uint32 iZoom)47 void AP_Frame::setZoomPercentage(UT_uint32 iZoom)
48 {
49 	XAP_Frame::setZoomPercentage(iZoom);
50 	_showDocument(iZoom);
51 }
52 
53 /*!
54  * This zooms an existing document in a frame by just changing the zoom
55  * in the graphics class.
56  */
quickZoom(UT_uint32 iZoom)57 void AP_Frame::quickZoom(UT_uint32 iZoom)
58 {
59 	bool bChanged = (getZoomPercentage() != iZoom);
60 	XAP_Frame::setZoomPercentage(iZoom);
61 	FV_View * pView = static_cast<FV_View *>(getCurrentView());
62 	if(!pView)
63 		return;
64 	if (bChanged)
65 	{
66 		FL_DocLayout * pDocLayout = pView->getLayout();
67 		pDocLayout->incrementGraphicTick();
68 		GR_Graphics * pOldGraphics = pView->getGraphics();
69 		pOldGraphics->setZoomPercentage(iZoom);
70 		pOldGraphics->clearFont();
71 
72 		if(pView->getViewMode() == VIEW_WEB)
73 		{
74 			UT_sint32 iAdjustZoom = pView->calculateZoomPercentForPageWidth();
75 			UT_Dimension orig_ut = DIM_IN;
76 			orig_ut = pDocLayout->m_docViewPageSize.getDims();
77 			double orig_width = pDocLayout->getDocument()->m_docPageSize.Width(orig_ut);
78 			double orig_height = pDocLayout->getDocument()->m_docPageSize.Height(orig_ut);
79 			double rat = static_cast<double>(iAdjustZoom)/static_cast<double>(iZoom) ;
80 			double new_width = orig_width*rat;
81 			UT_DEBUGMSG(("AP_Frame zoom VIEW_WEB old width %f new width %f old height %f \n",orig_width,new_width,orig_height));
82 			bool p = pDocLayout->m_docViewPageSize.isPortrait();
83 			pDocLayout->m_docViewPageSize.Set(new_width,orig_height,orig_ut);
84 			pDocLayout->m_docViewPageSize.Set(fp_PageSize::psCustom,orig_ut);
85 			if(p)
86 			{
87 				pDocLayout->m_docViewPageSize.setPortrait();
88 			}
89 			else
90 			{
91 				pDocLayout->m_docViewPageSize.setLandscape();
92 			}
93 			fl_SectionLayout* pSL = pDocLayout->getFirstSection();
94 			while (pSL)
95 			{
96 				pSL->lookupMarginProperties();
97 				pSL = static_cast<fl_SectionLayout *>(pSL->getNext());
98 			}
99 			pView->rebuildLayout();
100 			pDocLayout->formatAll();
101 
102 		}
103 		AP_TopRuler * pTop = pView->getTopRuler();
104 		if(pTop)
105 		{
106 			pTop->setZoom(iZoom);
107 		}
108 		AP_LeftRuler * pLeft = pView->getLeftRuler();
109 		if(pLeft)
110 		{
111 			pLeft->setZoom(iZoom);
112 		}
113 		pView->calculateNumHorizPages();
114 		setYScrollRange();
115 		setXScrollRange();
116 		if(pTop && !pTop->isHidden())
117 		{
118 			pTop->queueDraw();
119 		}
120 		if(pLeft && !pLeft->isHidden())
121 		{
122 			pLeft->queueDraw();
123 		}
124 //
125 // Redraw the entire screen
126 //
127 		pView->setPoint(pView->getPoint()); // place the cursor correctly
128 		pView->ensureInsertionPointOnScreen(); // on the screen
129 		pView->updateScreen(false);
130 	}
131 	else
132 	{
133 //
134 // Redraw the entire screen
135 //
136 		pView->updateScreen(false);
137 	}
138 
139 	// Notify listeners of new zoom (to update the zoom combo in toolbar)
140 	// We do this regardless of bChanged since a change from 100% zoom to
141 	// "Page Width" zoom may not change the logical zoom level.
142 	pView->notifyListeners(AV_CHG_ALL);
143 }
144 
getZoomPercentage(void)145 UT_uint32 AP_Frame::getZoomPercentage(void)
146 {
147 	// !m_pData can happen when calling dlgZoom from AbiCommand;
148 	// !m_pG can happen when called from an uninitialized abiwidget
149 	if(m_pData && static_cast<AP_FrameData*>(m_pData)->m_pG)
150 		return static_cast<AP_FrameData*>(m_pData)->m_pG->getZoomPercentage();
151 
152 	return 100; // 100 seems like the sanest default
153 }
154 
~AP_Frame()155 AP_Frame::~AP_Frame()
156 {
157 }
158 
159 
initFrameData()160 bool AP_Frame::initFrameData()
161 {
162 	UT_ASSERT_HARMLESS(!static_cast<AP_FrameData*>(m_pData));
163 
164 	AP_FrameData* pData = new AP_FrameData();
165 
166 	m_pData = static_cast<void*>(pData);
167 	return (pData ? true : false);
168 }
169 
killFrameData()170 void AP_Frame::killFrameData()
171 {
172 	AP_FrameData* pData = static_cast<AP_FrameData*>(m_pData);
173 	DELETEP(pData);
174 	m_pData = NULL;
175 }
176 
_loadDocument(const char * szFilename,IEFileType ieft,bool createNew)177 UT_Error AP_Frame::_loadDocument(const char * szFilename, IEFileType ieft,
178 				     bool createNew)
179 {
180 #ifdef DEBUG
181 	if (szFilename) {
182 		UT_DEBUGMSG(("DOM: trying to load %s (%d, %d)\n", szFilename, ieft, createNew));
183 	}
184 	else {
185 		UT_DEBUGMSG(("DOM: trying to load %s (%d, %d)\n", "(NULL)", ieft, createNew));
186 	}
187 #endif
188 
189 	// are we replacing another document?
190 	if (m_pDoc)
191 	{
192 		// yep.  first make sure it's OK to discard it,
193 		// TODO: query user if dirty...
194 	}
195 
196 	// load a document into the current frame.
197 	// if no filename, create a new document.
198 	if(XAP_App::getApp()->findFrame(this) < 0)
199 	{
200 		XAP_App::getApp()->rememberFrame(this);
201 	}
202 	AD_Document * pNewDoc = new PD_Document();
203 	UT_return_val_if_fail (pNewDoc, UT_ERROR);
204 	UT_Error errorCode = UT_OK;
205 
206 	if (!szFilename || !*szFilename)
207 	{
208 		pNewDoc->newDocument();
209 		m_iUntitled = _getNextUntitledNumber();
210 		goto ReplaceDocument;
211 	}
212 	errorCode = pNewDoc->readFromFile(szFilename, ieft);
213 	if (UT_IS_IE_SUCCESS(errorCode))
214 		goto ReplaceDocument;
215 
216 	if (createNew)
217 	  {
218 	    // we have a file name but couldn't load it
219 	    pNewDoc->newDocument();
220 
221 	    // here, we want to open a new document if it doesn't exist.
222 	    // errorCode could also take several other values, indicating
223 	    // that the document exists but for some reason we could not
224 	    // open it. in those cases, we do not wish to overwrite the
225 	    // existing documents, but instead open a new blank document.
226 	    // this fixes bug 1668 - DAL
227 
228 		UT_DEBUGMSG(("Could not open the document - create new istead error code is %d \n", errorCode));
229 	    if ( UT_IE_FILENOTFOUND == errorCode ||  UT_INVALIDFILENAME == errorCode  )
230 		{
231 			UT_DEBUGMSG(("File NOT found!! Create new doc \n"));
232 			if( UT_IE_FILENOTFOUND == errorCode)
233 			{
234 				errorCode = pNewDoc->saveAs(szFilename, ieft);
235 			}
236 			else
237 			{
238 				errorCode = 0;
239 			}
240 			UT_DEBUGMSG(("errocode after save is %d\n",errorCode));
241 		}
242 	  }
243 	if (!errorCode)
244 	  goto ReplaceDocument;
245 
246 	UT_DEBUGMSG(("ap_Frame: could not open the file [%s]\n",szFilename));
247 	UNREFP(pNewDoc);
248 	return errorCode;
249 
250 ReplaceDocument:
251 	XAP_App::getApp()->forgetClones(this);
252 	UT_DEBUGMSG(("Doing replace document \n"));
253 
254 	// NOTE: prior document is discarded in _showDocument()
255 	m_pDoc = pNewDoc;
256 	return errorCode;
257 }
258 
_loadDocument(GsfInput * input,IEFileType ieft)259 UT_Error AP_Frame::_loadDocument(GsfInput * input, IEFileType ieft)
260 {
261 	UT_return_val_if_fail (input != NULL, UT_ERROR);
262 
263 	// are we replacing another document?
264 	if (m_pDoc)
265 	{
266 		// yep.  first make sure it's OK to discard it,
267 		// TODO: query user if dirty...
268 	}
269 
270 	// load a document into the current frame.
271 	// if no filename, create a new document.
272 	if(XAP_App::getApp()->findFrame(this) < 0)
273 	{
274 		XAP_App::getApp()->rememberFrame(this);
275 	}
276 	AD_Document * pNewDoc = new PD_Document();
277 	UT_return_val_if_fail (pNewDoc, UT_ERROR);
278 
279 	UT_Error errorCode;
280 	errorCode = static_cast<PD_Document*>(pNewDoc)->readFromFile(input, ieft);
281 	if (errorCode)
282 		{
283 			UT_DEBUGMSG(("ap_Frame: could not open the file\n"));
284 			UNREFP(pNewDoc);
285 			return errorCode;
286 		}
287 
288 	XAP_App::getApp()->forgetClones(this);
289 	UT_DEBUGMSG(("Doing replace document \n"));
290 
291 	// NOTE: prior document is discarded in _showDocument()
292 	m_pDoc = pNewDoc;
293 	return UT_OK;
294 }
295 
_importDocument(const char * szFilename,int ieft,bool markClean)296 UT_Error AP_Frame::_importDocument(const char * szFilename, int ieft,
297 									  bool markClean)
298 {
299 	UT_DEBUGMSG(("DOM: trying to import %s (%d, %d)\n", szFilename, ieft, markClean));
300 
301 	// are we replacing another document?
302 	if (m_pDoc)
303 	{
304 		// yep.  first make sure it's OK to discard it,
305 		// TODO: query user if dirty...
306 	}
307 
308 	// load a document into the current frame.
309 	// if no filename, create a new document.
310 
311 	AD_Document * pNewDoc = new PD_Document();
312 	UT_return_val_if_fail (pNewDoc, UT_ERROR);
313 
314 	if (!szFilename || !*szFilename)
315 	{
316 		pNewDoc->newDocument();
317 		goto ReplaceDocument;
318 	}
319 	UT_Error errorCode;
320 	errorCode = pNewDoc->importFile(szFilename, ieft, markClean);
321 	if (!errorCode)
322 		goto ReplaceDocument;
323 
324 	UT_DEBUGMSG(("ap_Frame: could not open the file [%s]\n",szFilename));
325 
326 	UNREFP(pNewDoc);
327 	return errorCode;
328 
329 ReplaceDocument:
330 	XAP_App::getApp()->forgetClones(this);
331 
332 	m_iUntitled = _getNextUntitledNumber();
333 
334 	// NOTE: prior document is discarded in _showDocument()
335 	m_pDoc = pNewDoc;
336 	return UT_OK;
337 }
338 
buildFrame(XAP_Frame * pF)339 XAP_Frame * AP_Frame::buildFrame(XAP_Frame * pF)
340 {
341 	UT_Error error = UT_OK;
342 	AP_Frame * pClone = static_cast<AP_Frame *>(pF);
343 	XAP_Frame::tZoomType iZoomType = pF->getZoomType();
344 	setZoomType(iZoomType);
345 	UT_uint32 iZoom = XAP_Frame::getZoomPercentage();
346 	ENSUREP_C(pClone);
347 	if (!pClone->initialize())
348 		goto Cleanup;
349 
350 	// we remember the view of the parent frame ...
351 	static_cast<AP_FrameData*>(pClone->m_pData)->m_pRootView = m_pView;
352 
353 	error = pClone->_showDocument(iZoom);
354 	if (error)
355 		goto Cleanup;
356 
357 	pClone->show();
358 	return static_cast<XAP_Frame *>(pClone);
359 
360  Cleanup:
361 	// clean up anything we created here
362 	if (pClone)
363 	{
364 		XAP_App::getApp()->forgetFrame(pClone);
365 		delete pClone;
366 	}
367 	return NULL;
368 }
369 
loadDocument(AD_Document * pDoc)370 UT_Error AP_Frame::loadDocument(AD_Document* pDoc) {
371 	bool bUpdateClones;
372 	UT_GenericVector<XAP_Frame*> vClones;
373 	XAP_App * pApp = XAP_App::getApp();
374 	UT_sint32 j = 0;
375 	if(pApp->findFrame(this) < 0)
376 	{
377 			pApp->rememberFrame(this);
378 	}
379 	bUpdateClones = (getViewNumber() > 0);
380 	if (bUpdateClones)
381 	{
382 		pApp->getClones(&vClones, this);
383 	}
384 	for(j=0; j<vClones.getItemCount();j++)
385 	{
386 		AP_Frame * pFrame = static_cast<AP_Frame *>(vClones.getNthItem(j));
387 		if(pApp->findFrame(pFrame) < 0)
388 		{
389 			pFrame->_replaceDocument(pDoc);
390 		}
391 	}
392 
393 	return _replaceDocument(pDoc);
394 }
395 
loadDocument(GsfInput * input,int ieft)396 UT_Error AP_Frame::loadDocument(GsfInput * input, int ieft)
397 {
398 	bool bUpdateClones;
399 	UT_GenericVector<XAP_Frame*> vClones;
400 	XAP_App * pApp = XAP_App::getApp();
401 	UT_sint32 j = 0;
402 	if(pApp->findFrame(this) < 0)
403 	{
404 			pApp->rememberFrame(this);
405 	}
406 	bUpdateClones = (getViewNumber() > 0);
407 	if (bUpdateClones)
408 	{
409 		pApp->getClones(&vClones, this);
410 	}
411 	for(j=0; j<vClones.getItemCount();j++)
412 	{
413 		XAP_Frame * pFrame = vClones.getNthItem(j);
414 		if(pApp->findFrame(pFrame) < 0)
415 		{
416 			pApp->rememberFrame(pFrame,this);
417 		}
418 	}
419 	UT_Error errorCode;
420 	errorCode =  _loadDocument(input, static_cast<IEFileType>(ieft));
421 	if (!UT_IS_IE_SUCCESS(errorCode))
422 	{
423 		// we could not load the document.
424 		// we cannot complain to the user here, we don't know
425 		// if the app is fully up yet.  we force our caller
426 		// to deal with the problem.
427 		return errorCode;
428 	}
429 	XAP_Frame::tZoomType iZoomType;
430 	UT_uint32 iZoom = getNewZoom(&iZoomType);
431 	setZoomType(iZoomType);
432 	if(pApp->findFrame(this) < 0)
433 	{
434 		pApp->rememberFrame(this);
435 	}
436 	if (bUpdateClones)
437 	{
438 		for (UT_sint32 i = 0; i < vClones.getItemCount(); i++)
439 		{
440 			AP_Frame * pFrame = static_cast<AP_Frame*>(vClones.getNthItem(i));
441 			if(pFrame != this)
442 			{
443 				pFrame->_replaceDocument(m_pDoc);
444 			}
445 		}
446 	}
447 
448 	return _showDocument(iZoom);
449 }
450 
loadDocument(const char * szFilename,int ieft,bool createNew)451 UT_Error AP_Frame::loadDocument(const char * szFilename, int ieft, bool createNew)
452 {
453 	bool bUpdateClones;
454 	UT_GenericVector<XAP_Frame*> vClones;
455 	XAP_App * pApp = XAP_App::getApp();
456 	UT_sint32 j = 0;
457 	if(pApp->findFrame(this) < 0)
458 	{
459 			pApp->rememberFrame(this);
460 	}
461 	bUpdateClones = (getViewNumber() > 0);
462 	if (bUpdateClones)
463 	{
464 		pApp->getClones(&vClones, this);
465 	}
466 	for(j=0; j<vClones.getItemCount();j++)
467 	{
468 		XAP_Frame * pFrame = vClones.getNthItem(j);
469 		if(pApp->findFrame(pFrame) < 0)
470 		{
471 			pApp->rememberFrame(pFrame,this);
472 		}
473 	}
474 	UT_Error errorCode;
475 	errorCode =  _loadDocument(szFilename, static_cast<IEFileType>(ieft), createNew);
476 	if (!UT_IS_IE_SUCCESS(errorCode))
477 	{
478 		// we could not load the document.
479 		// we cannot complain to the user here, we don't know
480 		// if the app is fully up yet.  we force our caller
481 		// to deal with the problem.
482 		return errorCode;
483 	}
484 	XAP_Frame::tZoomType iZoomType;
485 	UT_uint32 iZoom = getNewZoom(&iZoomType);
486 	setZoomType(iZoomType);
487 	if(pApp->findFrame(this) < 0)
488 	{
489 		pApp->rememberFrame(this);
490 	}
491 	if (bUpdateClones)
492 	{
493 		for (UT_sint32 i = 0; i < vClones.getItemCount(); i++)
494 		{
495 			AP_Frame * pFrame = static_cast<AP_Frame*>(vClones.getNthItem(i));
496 			if(pFrame != this)
497 			{
498 				pFrame->_replaceDocument(m_pDoc);
499 			}
500 		}
501 	}
502 
503 	UT_Error errorCode2 =  _showDocument(iZoom);
504     if((errorCode2 == UT_OK) && (errorCode == UT_IE_TRY_RECOVER))
505     {
506         return errorCode;
507     }
508     return errorCode2;
509 }
510 
loadDocument(const char * szFilename,int ieft)511 UT_Error AP_Frame::loadDocument(const char * szFilename, int ieft)
512 {
513   return loadDocument(szFilename, ieft, false);
514 }
515 
importDocument(const char * szFilename,int ieft,bool markClean)516 UT_Error AP_Frame::importDocument(const char * szFilename, int ieft, bool markClean)
517 {
518 	bool bUpdateClones;
519 	UT_GenericVector<XAP_Frame*> vClones;
520 	XAP_App * pApp = XAP_App::getApp();
521 
522 	bUpdateClones = (getViewNumber() > 0);
523 	if (bUpdateClones)
524 	{
525 		pApp->getClones(&vClones, this);
526 	}
527 	UT_Error errorCode;
528 	errorCode =  _importDocument(szFilename, static_cast<IEFileType>(ieft), markClean);
529 	if (!UT_IS_IE_SUCCESS(errorCode))
530 	{
531 		return errorCode;
532 	}
533 
534 	if (bUpdateClones)
535 	{
536 		for (UT_sint32 i = 0; i < vClones.getItemCount(); i++)
537 		{
538 			AP_Frame * pFrame = static_cast<AP_Frame *>(vClones.getNthItem(i));
539 			if(pFrame != this)
540 			{
541 				pFrame->_replaceDocument(m_pDoc);
542 			}
543 		}
544 	}
545 	XAP_Frame::tZoomType iZoomType;
546 	UT_uint32 iZoom = getNewZoom(&iZoomType);
547 	setZoomType(iZoomType);
548 	UT_Error errorCode2 =  _showDocument(iZoom);
549     if((errorCode2 == UT_OK) && (errorCode == UT_IE_TRY_RECOVER))
550     {
551         return errorCode;
552     }
553     return errorCode2;
554 }
555 
556 /*!
557  * This method returns the zoomPercentage of the new frame.
558  * Logic goes like this.
559  * If there is a valid last focussed frame return the zoom and zoom type
560  * for that.
561  * Otherwise use the preference value.
562  */
getNewZoom(XAP_Frame::tZoomType * tZoom)563 UT_uint32 AP_Frame::getNewZoom(XAP_Frame::tZoomType * tZoom)
564 {
565 	UT_GenericVector<XAP_Frame*> vecClones;
566 	XAP_Frame *pF = NULL;
567 	XAP_App * pApp = XAP_App::getApp();
568 	UT_return_val_if_fail (pApp, 0);
569 	XAP_Frame * pLastFrame = pApp->getLastFocussedFrame();
570 	UT_uint32 iZoom = 100;
571 	if(pLastFrame == NULL)
572 	{
573 		UT_String sZoom;
574 		pApp->getPrefsValue(XAP_PREF_KEY_ZoomType, sZoom);
575 		*tZoom = getZoomType();
576 		if( (g_ascii_strcasecmp( sZoom.c_str(), "Width" ) == 0 ) || (g_ascii_strcasecmp( sZoom.c_str(), "Page" ) == 0 ))
577 		{
578 			iZoom = 100;
579 		}
580 		else
581 		{
582 			iZoom =  atoi( sZoom.c_str() );
583 		}
584 		return iZoom;
585 	}
586 	else
587 	{
588 		UT_uint32 nFrames = getViewNumber();
589 
590 		if(nFrames == 0)
591 		{
592 			iZoom = pLastFrame->getZoomPercentage();
593 			*tZoom = pLastFrame->getZoomType();
594 			return iZoom;
595 		}
596 		XAP_App::getApp()->getClones(&vecClones,this);
597 		UT_sint32 i =0;
598 		bool bMatch = false;
599 		for (i=0; !bMatch && (i< vecClones.getItemCount()); i++)
600 		{
601 			pF = static_cast<XAP_Frame *>(vecClones.getNthItem(i));
602 			bMatch = (pF == pLastFrame);
603 		}
604 		if(bMatch)
605 		{
606 			iZoom = pLastFrame->getZoomPercentage();
607 			*tZoom = pLastFrame->getZoomType();
608 			return iZoom;
609 		}
610 	}
611 	iZoom = pF->getZoomPercentage();
612 	*tZoom = pF->getZoomType();
613 	return iZoom;
614 }
615 
_replaceDocument(AD_Document * pDoc)616 UT_Error AP_Frame::_replaceDocument(AD_Document * pDoc)
617 {
618 	// NOTE: prior document is discarded in _showDocument()
619 	m_pDoc = pDoc; // This was a REFP(pDoc) but it just a caused leak
620 	XAP_Frame::tZoomType iZoomType;
621 	UT_uint32 iZoom = getNewZoom(&iZoomType);
622 	setZoomType(iZoomType);
623 	UT_Error res = _showDocument(iZoom);
624 	// notify our listeners
625 	_signal(APF_ReplaceDocument);
626 	return res;
627 }
628 
_showDocument(UT_uint32 iZoom)629 UT_Error AP_Frame::_showDocument(UT_uint32 iZoom)
630 {
631 	if (!m_pDoc)
632 	{
633 		UT_DEBUGMSG(("Can't show a non-existent document\n"));
634 		return UT_IE_FILENOTFOUND;
635 	}
636 	if(isFrameLocked())
637 	{
638 		UT_DEBUGMSG(("_showDocument: Nasty race bug, please fix me!! \n"));
639 		UT_ASSERT_HARMLESS(0);
640 		return  UT_IE_ADDLISTENERERROR;
641 	}
642 	setFrameLocked(true);
643 	if (!static_cast<AP_FrameData*>(m_pData))
644 	{
645 		UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
646 		setFrameLocked(false);
647 		return UT_IE_IMPORTERROR;
648 	}
649 
650 // 	static_cast<XAP_FrameImpl *>(m_pFrameImpl)->setShowDocLocked(true);
651 
652 	GR_Graphics * pG = NULL;
653 	FL_DocLayout * pDocLayout = NULL;
654 	AV_View * pView = NULL;
655 	AV_ScrollObj * pScrollObj = NULL;
656 	ap_ViewListener * pViewListener = NULL;
657 	AD_Document * pOldDoc = NULL;
658 	ap_Scrollbar_ViewListener * pScrollbarViewListener = NULL;
659 	AV_ListenerId lid;
660 	AV_ListenerId lidScrollbarViewListener;
661 
662 	xxx_UT_DEBUGMSG(("_showDocument: Initial m_pView %x \n",m_pView));
663 
664 	if(iZoom < XAP_DLG_ZOOM_MINIMUM_ZOOM)
665 		iZoom = 100;
666 	else if (iZoom > XAP_DLG_ZOOM_MAXIMUM_ZOOM)
667 		iZoom = 100;
668 	UT_DEBUGMSG(("!!!!!!!!! _showdOCument: Initial izoom is %d \n",iZoom));
669 
670 	if (!_createViewGraphics(pG, iZoom))
671 		goto Cleanup;
672 
673 	pDocLayout = new FL_DocLayout(static_cast<PD_Document *>(m_pDoc), pG);
674 	ENSUREP_C(pDocLayout);
675 
676 	pView = new FV_View(XAP_App::getApp(), this, pDocLayout);
677 	ENSUREP_C(pView);
678 
679 	if(getZoomType() == XAP_Frame::z_PAGEWIDTH)
680 	{
681 		iZoom = pView->calculateZoomPercentForPageWidth();
682 		pG->setZoomPercentage(iZoom);
683 	}
684 	else if(getZoomType() == XAP_Frame::z_WHOLEPAGE)
685 	{
686 		iZoom = pView->calculateZoomPercentForWholePage();
687 		pG->setZoomPercentage(iZoom);
688 	}
689 	UT_DEBUGMSG(("!!!!!!!!! _showdOCument: izoom is %d \n",iZoom));
690 	XAP_Frame::setZoomPercentage(iZoom);
691 	_setViewFocus(pView);
692 
693 	if (!_createScrollBarListeners(pView, pScrollObj, pViewListener, pScrollbarViewListener,
694 				       lid, lidScrollbarViewListener))
695 		goto Cleanup;
696 	if(getFrameMode() ==XAP_NormalFrame)
697 	{
698 		_bindToolbars(pView);
699 	}
700 	_replaceView(pG, pDocLayout, pView, pScrollObj, pViewListener, pOldDoc,
701 		     pScrollbarViewListener, lid, lidScrollbarViewListener, iZoom);
702 
703 	setXScrollRange();
704 	setYScrollRange();
705 
706 	m_pView->draw();
707 
708 	if ( static_cast<AP_FrameData*>(m_pData)->m_bShowRuler  )
709 	{
710 		if ( static_cast<AP_FrameData*>(m_pData)->m_pTopRuler )
711 		{
712 			static_cast<AP_FrameData*>(m_pData)->m_pTopRuler->setZoom(iZoom);
713 			static_cast<AP_FrameData*>(m_pData)->m_pTopRuler->queueDraw();
714 		}
715 		if ( static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler )
716 		{
717 			static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler->setZoom(iZoom);
718 			static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler->queueDraw();
719 		}
720 	}
721 	if(isStatusBarShown())
722 	{
723 		if (static_cast<AP_FrameData*>(m_pData)->m_pStatusBar)
724 			static_cast<AP_FrameData*>(m_pData)->m_pStatusBar->notify(m_pView, AV_CHG_ALL);
725 	}
726 	m_pView->notifyListeners(AV_CHG_ALL);
727 	m_pView->focusChange(AV_FOCUS_HERE);
728 
729 	//static_cast<XAP_FrameImpl *>(m_pFrameImpl)->setShowDocLocked(false);
730 	setFrameLocked(false);
731 	return UT_OK;
732 
733 Cleanup:
734 	// clean up anything we created here
735 	DELETEP(pG);
736 	DELETEP(pDocLayout);
737 	DELETEP(pView);
738 	DELETEP(pViewListener);
739 	DELETEP(pScrollObj);
740 	DELETEP(pScrollbarViewListener);
741 
742 	// change back to prior document
743 	UNREFP(m_pDoc);
744 	setFrameLocked(false);
745 	UT_return_val_if_fail(static_cast<AP_FrameData*>(m_pData)->m_pDocLayout, UT_IE_ADDLISTENERERROR);
746 	m_pDoc = static_cast<AP_FrameData*>(m_pData)->m_pDocLayout->getDocument();
747 	//static_cast<XAP_FrameImpl *>(m_pFrameImpl)->setShowDocLocked(false);
748 	return UT_IE_ADDLISTENERERROR;
749 }
750 
_replaceView(GR_Graphics * pG,FL_DocLayout * pDocLayout,AV_View * pView,AV_ScrollObj * pScrollObj,ap_ViewListener * pViewListener,AD_Document * pOldDoc,ap_Scrollbar_ViewListener * pScrollbarViewListener,AV_ListenerId lid,AV_ListenerId lidScrollbarViewListener,UT_uint32 iZoom)751 void AP_Frame::_replaceView(GR_Graphics * pG, FL_DocLayout *pDocLayout,
752 			    AV_View *pView, AV_ScrollObj * pScrollObj,
753 			    ap_ViewListener *pViewListener, AD_Document *pOldDoc,
754 			    ap_Scrollbar_ViewListener *pScrollbarViewListener,
755 			    AV_ListenerId lid, AV_ListenerId lidScrollbarViewListener,
756 			    UT_uint32 iZoom)
757 {
758 	bool holdsSelection = false, hadView = true;
759 	PD_DocumentRange range;
760 	PT_DocPosition inspt = 0;
761 
762 	// we want to remember point/selection when that is appropriate, which is when the new view is a
763 	// view of the same doc as the old view, or if this frame is being cloned from an existing frame
764 
765 	// these are the view and doc from which this frame is being cloned
766 	FV_View * pRootView = NULL; // this should really be const, but
767 								// getDocumentRangeOfCurrentSelection() is not
768 	const AD_Document * pRootDoc = NULL;
769 
770 	if (m_pView && !m_pView->isSelectionEmpty ())
771 	{
772 		holdsSelection = true;
773 		static_cast<FV_View*>(m_pView)->getDocumentRangeOfCurrentSelection (&range);
774 	} else if (m_pView)
775 	{
776 		inspt = static_cast<FV_View*>(m_pView)->getInsPoint ();
777 	}
778 	else if(static_cast<AP_FrameData*>(m_pData)->m_pRootView)
779 	{
780 		pRootView = static_cast<FV_View*>(static_cast<AP_FrameData*>(m_pData)->m_pRootView);
781 		pRootDoc = pRootView->getDocument();
782 
783 		if (!pRootView->isSelectionEmpty())
784 		{
785 			holdsSelection = true;
786 			pRootView->getDocumentRangeOfCurrentSelection (&range);
787 		} else if (pRootView)
788 		{
789 			inspt = pRootView->getInsPoint ();
790 		}
791 		else
792 			hadView = false;
793 
794 		// we want to set m_pData->m_pRootView to NULL, since it has fullfilled its function and we
795 		// do not want any dead pointers hanging around
796 		static_cast<AP_FrameData*>(m_pData)->m_pRootView = NULL;
797 	}
798 	else
799 		hadView = false;
800 
801 	// switch to new view, cleaning up previous settings
802 	if (static_cast<AP_FrameData*>(m_pData)->m_pDocLayout)
803 	{
804 		pOldDoc = (static_cast<AP_FrameData*>(m_pData)->m_pDocLayout->getDocument());
805 	}
806 
807 	REPLACEP(static_cast<AP_FrameData*>(m_pData)->m_pG, pG);
808 	REPLACEP(static_cast<AP_FrameData*>(m_pData)->m_pDocLayout, pDocLayout);
809 
810 	bool bSameDocument = false; // be cautious ...
811 
812 	if(!pOldDoc)
813 	{
814 		// this is the case when this is a new frame unrelated to anything, or a frame cloned from
815 		// existing frame
816 		if(pRootDoc == m_pDoc)
817 		{
818 			// we have been cloned from a frame which related to the same document
819 			bSameDocument = true;
820 		}
821 	}
822 	else if (pOldDoc != m_pDoc)
823 	{
824 	        static_cast<PD_Document *>(pOldDoc)->changeConnectedDocument(static_cast<PD_Document *>(m_pDoc));
825 		UNREFP(pOldDoc);
826 	}
827 	else
828 	{
829 		// pOldDoc == m_pDoc
830 		bSameDocument = true;
831 	}
832 
833 	AV_View * pReplacedView = m_pView;
834 	m_pView = pView;
835 
836 	XAP_App::getApp()->setViewSelection(NULL);
837 
838 	REPLACEP(m_pScrollObj, pScrollObj);
839 	REPLACEP(m_pViewListener, pViewListener);
840 	m_lid = lid;
841 	REPLACEP(m_pScrollbarViewListener, pScrollbarViewListener);
842 	m_lidScrollbarViewListener = lidScrollbarViewListener;
843 
844 	m_pView->addScrollListener(m_pScrollObj);
845 
846 	// Associate the new view with the existing TopRuler, LeftRuler.
847 	// Because of the binding to the actual on-screen widgets we do
848 	// not destroy and recreate the TopRuler, LeftRuler when we change
849 	// views, like we do for all the other objects.  We also do not
850 	// allocate the TopRuler, LeftRuler  here; that is done as the
851 	// frame is created.
852 	if ( static_cast<AP_FrameData*>(m_pData)->m_bShowRuler )
853 	{
854 		if ( static_cast<AP_FrameData*>(m_pData)->m_pTopRuler )
855 			static_cast<AP_FrameData*>(m_pData)->m_pTopRuler->setView(pView, iZoom);
856 		if ( static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler )
857 			static_cast<AP_FrameData*>(m_pData)->m_pLeftRuler->setView(pView, iZoom);
858 	}
859 
860 	if ( static_cast<AP_FrameData*>(m_pData)->m_pStatusBar && (getFrameMode() != XAP_NoMenusWindowLess))
861 		static_cast<AP_FrameData*>(m_pData)->m_pStatusBar->setView(pView);
862 	static_cast<FV_View *>(m_pView)->setShowPara(static_cast<AP_FrameData*>(m_pData)->m_bShowPara);
863 
864 	pView->setInsertMode((static_cast<AP_FrameData*>(m_pData)->m_bInsertMode));
865 	m_pView->setWindowSize(_getDocumentAreaWidth(), _getDocumentAreaHeight());
866 
867 	updateTitle();
868 	XAP_App * pApp = XAP_App::getApp();
869 	if(pApp->findFrame(this) < 0)
870 	{
871 		pApp->rememberFrame(this);
872 	}
873 	//
874 	// Remove the old layout before we fill the layouts to prevent
875 	// stale pointers being accessed during the fill phase.
876 	//
877 	if(bSameDocument)
878 	{
879 		static_cast<PD_Document *>(m_pDoc)->disableListUpdates();
880 	}
881 	pDocLayout->fillLayouts();
882 	if(bSameDocument)
883 	{
884 		static_cast<PD_Document *>(m_pDoc)->enableListUpdates();
885 		static_cast<PD_Document *>(m_pDoc)->updateDirtyLists();
886 	}
887 
888 	// can only hold selection/point if the two views are for the same doc !!!
889 	if(bSameDocument)
890 	{
891 		FV_View * pFV_View = static_cast<FV_View*>(m_pView);
892 		if (holdsSelection)
893 			pFV_View->cmdSelect (range.m_pos1, range.m_pos2);
894 		else if (hadView)
895 			pFV_View->moveInsPtTo(inspt);
896 	}
897 
898 	if (XAP_FrameImpl * pFrameImpl = getFrameImpl())
899 	{
900 		pFrameImpl->notifyViewChanged(m_pView);
901 	}
902 	DELETEP(pReplacedView);
903 
904 	// notify our listeners
905 	_signal(APF_ReplaceView);
906 }
907 
registerListener(AP_FrameListener * pListener)908 UT_sint32 AP_Frame::registerListener(AP_FrameListener* pListener)
909 {
910 	UT_return_val_if_fail(pListener, -1);
911 	m_listeners.push_back(pListener); // TODO: look for gaps that we can reuse, caused by unregister calls - MARCM
912 	return m_listeners.size()-1;
913 }
914 
unregisterListener(UT_sint32 iListenerId)915 void AP_Frame::unregisterListener(UT_sint32 iListenerId)
916 {
917 	UT_return_if_fail(iListenerId >= 0);
918 	UT_return_if_fail(iListenerId >= static_cast<UT_sint32>(m_listeners.size()));
919 	m_listeners[iListenerId] = NULL;
920 }
921 
_signal(AP_FrameSignal sig)922 void AP_Frame::_signal(AP_FrameSignal sig)
923 {
924 	for (std::vector<AP_FrameListener*>::iterator it = m_listeners.begin(); it != m_listeners.end(); it++)
925 	{
926 		AP_FrameListener* pListener = *it;
927 		if (pListener)
928 			pListener->signalFrame(sig);
929 	}
930 }
931