/* AbiWord * Copyright (C) 1998-2000 AbiSource, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include "ut_types.h" #include "ut_debugmsg.h" #include "ut_assert.h" #include "ut_Win32Timer.h" #include "xap_ViewListener.h" #include "ap_FrameData.h" #include "xap_Win32Frame.h" #include "ev_Win32Toolbar.h" #include "xav_View.h" #include "xad_Document.h" #include "fv_View.h" #include "fl_DocLayout.h" #include "pd_Document.h" #include "gr_Win32Graphics.h" #include "xap_Scrollbar_ViewListener.h" #include "ap_Win32Frame.h" #include "xap_Win32App.h" #include "ev_Win32Mouse.h" #include "ev_Win32Keyboard.h" #include "ap_Win32TopRuler.h" #include "ap_Win32LeftRuler.h" #include "ev_Win32Menu.h" #include "ap_Win32StatusBar.h" #include "ie_types.h" #include #include #ifndef SPI_GETWHEELSCROLLLINES #define SPI_GETWHEELSCROLLLINES 104 #endif #ifdef _MSC_VER // fix MSVC <= 6 (i.e. upto V.12+) bug #define for if (0) {} else for #endif int GetMouseWheelLines() { OSVERSIONINFO Info = { 0 }; Info.dwOSVersionInfoSize = sizeof(Info); if (GetVersionEx(&Info) && Info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && Info.dwMajorVersion == 4 && Info.dwMinorVersion == 0) { // Win95 UINT msgMSHWheelGetScrollLines = RegisterWindowMessage(MSH_SCROLL_LINES); HWND hdlMSHWheel = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); if (hdlMSHWheel && msgMSHWheelGetScrollLines) { return SendMessage(hdlMSHWheel, msgMSHWheelGetScrollLines, 0, 0); } } else { // Win98, NT, 2K UINT nScrollLines; if (SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, (PVOID) &nScrollLines, 0)) { return nScrollLines; } } return 3; } /*****************************************************************/ #define GWL(hwnd) (AP_Win32Frame*)GetWindowLong((hwnd), GWL_USERDATA) #define SWL(hwnd, f) (AP_Win32Frame*)SetWindowLong((hwnd), GWL_USERDATA,(LONG)(f)) #define ENSUREP(p) do { UT_ASSERT(p); if (!p) goto Cleanup; } while (0) /*****************************************************************/ static char s_ContainerWndClassName[256]; static char s_DocumentWndClassName[256]; static char s_LeftRulerWndClassName[256]; /*****************************************************************/ void AP_Win32Frame::_setVerticalScrollInfo(const SCROLLINFO * psi) { // internal interface to GetScrollInfo() and SetScrollInfo() // to deal with 16-bit limitations of SB_THUMBTRACK. UT_uint32 scale, x; for (x=psi->nMax, scale=0; (x > 0x0000ffff); x>>=1, scale++) ; m_vScale = scale; if (scale == 0) { SetScrollInfo(m_hWndVScroll, SB_CTL, psi, TRUE); return; } SCROLLINFO si = *psi; // structure copy si.nMin >>= scale; si.nMax >>= scale; si.nPos >>= scale; si.nPage >>= scale; SetScrollInfo(m_hWndVScroll, SB_CTL, &si, TRUE); return; } void AP_Win32Frame::_getVerticalScrollInfo(SCROLLINFO * psi) { GetScrollInfo(m_hWndVScroll, SB_CTL, psi); if (m_vScale) { psi->nMin <<= m_vScale; psi->nMax <<= m_vScale; psi->nPos <<= m_vScale; psi->nPage <<= m_vScale; } return; } /*****************************************************************/ void AP_Win32Frame::setZoomPercentage(UT_uint32 iZoom) { _showDocument(iZoom); } UT_uint32 AP_Win32Frame::getZoomPercentage(void) { return static_cast(m_pData)->m_pG->getZoomPercentage(); } UT_Error AP_Win32Frame::_showDocument(UT_uint32 iZoom) { if (!m_pDoc) { UT_DEBUGMSG(("Can't show a non-existent document\n")); return UT_IE_FILENOTFOUND; } if (!m_pData) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); return UT_IE_IMPORTERROR; } GR_Win32Graphics* pG = 0; FL_DocLayout* pDocLayout = 0; AV_View* pView = 0; AV_ScrollObj* pScrollObj = 0; ap_ViewListener* pViewListener = 0; AD_Document* pOldDoc = 0; ap_Scrollbar_ViewListener* pScrollbarViewListener = 0; AV_ListenerId lid; AV_ListenerId lidScrollbarViewListener; UT_uint32 point = 0; HWND hwnd = m_hwndDocument; pG = new GR_Win32Graphics(GetDC(hwnd), hwnd, getApp()); ENSUREP(pG); pG->setZoomPercentage(iZoom); pDocLayout = new FL_DocLayout(static_cast(m_pDoc), pG); ENSUREP(pDocLayout); // pDocLayout->formatAll(); pView = new FV_View(getApp(), this, pDocLayout); ENSUREP(pView); // pDocLayout->fillLayouts(); // The "AV_ScrollObj pScrollObj" receives // send{Vertical,Horizontal}ScrollEvents // from both the scroll-related edit methods // and from the UI callbacks. // // The "ap_ViewListener pViewListener" receives // change notifications as the document changes. // This ViewListener is responsible for keeping // the title-bar up to date (primarily title // changes, dirty indicator, and window number). // // The "ap_Scrollbar_ViewListener pScrollbarViewListener" // receives change notifications as the doucment changes. // This ViewListener is responsible for recalibrating the // scrollbars as pages are added/removed from the document. // // Each Toolbar will also get a ViewListener so that // it can update toggle buttons, and other state-indicating // controls on it. // // TODO we ***really*** need to re-do the whole scrollbar thing. // TODO we have an addScrollListener() using an m_pScrollObj // TODO and a View-Listener, and a bunch of other widget stuff. // TODO and its very confusing. pScrollObj = new AV_ScrollObj(this,_scrollFuncX,_scrollFuncY); ENSUREP(pScrollObj); pViewListener = new ap_ViewListener(this); ENSUREP(pViewListener); pScrollbarViewListener = new ap_Scrollbar_ViewListener(this,pView); ENSUREP(pScrollbarViewListener); if (!pView->addListener(pViewListener,&lid) || !pView->addListener(pScrollbarViewListener, &lidScrollbarViewListener)) { goto Cleanup; } { const UT_uint32 nrToolbars = m_vecToolbarLayoutNames.getItemCount(); for (UT_uint32 k = 0; k < nrToolbars; ++k) { // TODO Toolbars are a frame-level item, but a view-listener is // TODO a view-level item. I've bound the toolbar-view-listeners // TODO to the current view within this frame and have code in the // TODO toolbar to allow the view-listener to be rebound to a different // TODO view. in the future, when we have support for multiple views // TODO in the frame (think splitter windows), we will need to have // TODO a loop like this to help change the focus when the current // TODO view changes. EV_Win32Toolbar* pWin32Toolbar = (EV_Win32Toolbar *)m_vecToolbars.getNthItem(k); pWin32Toolbar->bindListenerToView(pView); } } /**************************************************************** ***************************************************************** ** If we reach this point, everything for the new document has ** been created. We can now safely replace the various fields ** within the structure. Nothing below this point should fail. ***************************************************************** ****************************************************************/ // switch to new view, cleaning up previous settings if (static_cast(m_pData)->m_pDocLayout) { pOldDoc = static_cast(m_pData)->m_pDocLayout->getDocument(); } REPLACEP(static_cast(m_pData)->m_pG, pG); REPLACEP(static_cast(m_pData)->m_pDocLayout, pDocLayout); if (pOldDoc != m_pDoc) { UNREFP(pOldDoc); } { const AV_Focus prevFocus = m_pView ? m_pView->getFocus() : AV_FOCUS_NONE; REPLACEP(m_pView, pView); m_pView->setFocus(prevFocus); } REPLACEP(m_pScrollObj, pScrollObj); REPLACEP(m_pViewListener, pViewListener); m_lid = lid; REPLACEP(m_pScrollbarViewListener,pScrollbarViewListener); m_lidScrollbarViewListener = lidScrollbarViewListener; m_pView->addScrollListener(m_pScrollObj); // Associate the new view with the existing TopRuler, LeftRuler. // Because of the binding to the actual on-screen widgets // we do not destroy and recreate the TopRuler,LeftRuler when we change // views, like we do for all the other objects. We also do not // allocate the TopRuler, LeftRuler here; that is done as the frame is // created. if (static_cast(m_pData)->m_pTopRuler) static_cast(m_pData)->m_pTopRuler->setView(pView, iZoom); if (static_cast(m_pData)->m_pLeftRuler) static_cast(m_pData)->m_pLeftRuler->setView(pView, iZoom); static_cast(m_pData)->m_pStatusBar->setView(pView); pView->setInsertMode(static_cast(m_pData)->m_bInsertMode); ((FV_View *) m_pView)->setShowPara(((AP_FrameData*)m_pData)->m_bShowPara); RECT r; GetClientRect(hwnd, &r); m_pView->setWindowSize(r.right - r.left, r.bottom - r.top); InvalidateRect(hwnd, NULL, TRUE); updateTitle(); pDocLayout->fillLayouts(); // we cannot do this before we fill the layout, because if we are // running in default RTL mode, the X scroll needs to be able to // have a valid block for its calculations setXScrollRange(); setYScrollRange(); if (m_pView != NULL) { // we cannot just set the insertion position to that of the previous // view, since the new document could be shorter or completely // different from the previous one (see bug 2615) // Instead we have to test that the original position is within // the editable bounds, and if not, we will set the point // to the end of the document (i.e., if reloading an earlier // version of the same document we try to get the point as near // the users editing position as possible point = ((FV_View *) m_pView)->getPoint(); PT_DocPosition posEOD; static_cast(pView)->getEditableBounds(true, posEOD, false); if(point > posEOD) point = posEOD; } if (point != 0) ((FV_View *) m_pView)->moveInsPtTo(point); m_pView->draw(); if (static_cast(m_pData)->m_pTopRuler) static_cast(m_pData)->m_pTopRuler->draw(NULL); if (static_cast(m_pData)->m_pLeftRuler) static_cast(m_pData)->m_pLeftRuler->draw(NULL); static_cast(m_pData)->m_pStatusBar->draw(); return UT_OK; Cleanup: // clean up anything we created here DELETEP(pG); DELETEP(pDocLayout); DELETEP(pView); DELETEP(pViewListener); DELETEP(pScrollObj); DELETEP(pScrollbarViewListener); // change back to prior document UNREFP(m_pDoc); m_pDoc = static_cast(m_pData)->m_pDocLayout->getDocument(); return UT_IE_ADDLISTENERERROR; } void AP_Win32Frame::setXScrollRange(void) { RECT r; GetClientRect(m_hwndDocument, &r); const UT_uint32 iWindowWidth = r.right - r.left; const UT_uint32 iWidth = static_cast(m_pData)->m_pDocLayout->getWidth(); SCROLLINFO si = { 0 }; si.cbSize = sizeof(si); si.fMask = SIF_ALL | SIF_DISABLENOSCROLL; si.nMin = 0; si.nMax = iWidth; si.nPos = ((m_pView) ? m_pView->getXScrollOffset() : 0); si.nPage = iWindowWidth; SetScrollInfo(m_hWndHScroll, SB_CTL, &si, TRUE); m_pView->sendHorizontalScrollEvent(si.nPos,si.nMax-si.nPage); } void AP_Win32Frame::setYScrollRange(void) { RECT r; GetClientRect(m_hwndDocument, &r); const UT_uint32 iWindowHeight = r.bottom - r.top; const UT_uint32 iHeight = static_cast(m_pData)->m_pDocLayout->getHeight(); SCROLLINFO si = { 0 }; si.cbSize = sizeof(si); si.fMask = SIF_ALL | SIF_DISABLENOSCROLL; si.nMin = 0; si.nMax = iHeight; si.nPos = ((m_pView) ? m_pView->getYScrollOffset() : 0); si.nPage = iWindowHeight; _setVerticalScrollInfo(&si); m_pView->sendVerticalScrollEvent(si.nPos,si.nMax-si.nPage); } bool AP_Win32Frame::RegisterClass(XAP_Win32App * app) { // NB: can't access 'this' members from a static member function if (!XAP_Win32Frame::RegisterClass(app)) return false; WNDCLASSEX wndclass; ATOM a; // register class for the container window (this will contain the document // and the rulers and the scroll bars) sprintf(s_ContainerWndClassName, "%sContainer", app->getApplicationName()); memset(&wndclass, 0, sizeof(wndclass)); wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_DBLCLKS | CS_OWNDC; wndclass.lpfnWndProc = AP_Win32Frame::_ContainerWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = app->getInstance(); wndclass.hIcon = NULL; wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = s_ContainerWndClassName; wndclass.hIconSm = NULL; a = RegisterClassEx(&wndclass); UT_ASSERT(a); // register class for the actual document window sprintf(s_DocumentWndClassName, "%sDocument", app->getApplicationName()); memset(&wndclass, 0, sizeof(wndclass)); wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_DBLCLKS | CS_OWNDC; wndclass.lpfnWndProc = AP_Win32Frame::_DocumentWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = app->getInstance(); wndclass.hIcon = NULL; wndclass.hCursor = NULL; wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = s_DocumentWndClassName; wndclass.hIconSm = NULL; a = RegisterClassEx(&wndclass); UT_ASSERT(a); if (!AP_Win32TopRuler::RegisterClass(app) || !AP_Win32LeftRuler::RegisterClass(app) || !AP_Win32StatusBar::RegisterClass(app)) { return false; } return true; } AP_Win32Frame::AP_Win32Frame(XAP_Win32App * app) : XAP_Win32Frame(app), m_bMouseWheelTrack(false), m_bMouseActivateReceived(false), m_hWndHScroll(0), m_hWndVScroll(0), m_hWndGripperHack(0) { m_hwndContainer = NULL; m_hwndTopRuler = NULL; m_hwndLeftRuler = NULL; m_hwndDocument = NULL; m_hwndStatusBar = NULL; } AP_Win32Frame::AP_Win32Frame(AP_Win32Frame * f) : XAP_Win32Frame(static_cast(f)), m_bMouseWheelTrack(false), m_bMouseActivateReceived(false), m_hWndHScroll(0), m_hWndVScroll(0), m_bFirstAfterFocus(false), m_hWndGripperHack(0) { m_hwndContainer = NULL; m_hwndTopRuler = NULL; m_hwndLeftRuler = NULL; m_hwndDocument = NULL; m_hwndStatusBar = NULL; } AP_Win32Frame::~AP_Win32Frame(void) { killFrameData(); } bool AP_Win32Frame::initialize(void) { if (!initFrameData()) return false; if (!XAP_Win32Frame::initialize(AP_PREF_KEY_KeyBindings,AP_PREF_DEFAULT_KeyBindings, AP_PREF_KEY_MenuLayout, AP_PREF_DEFAULT_MenuLayout, AP_PREF_KEY_MenuLabelSet, AP_PREF_DEFAULT_MenuLabelSet, AP_PREF_KEY_ToolbarLayouts, AP_PREF_DEFAULT_ToolbarLayouts, AP_PREF_KEY_ToolbarLabelSet, AP_PREF_DEFAULT_ToolbarLabelSet)) return false; _createTopLevelWindow(); _showOrHideToolbars(); _showOrHideStatusbar(); return true; } XAP_Frame* AP_Win32Frame::cloneFrame(void) { AP_Win32Frame* pClone = new AP_Win32Frame(this); UT_ASSERT(pClone); return pClone; } XAP_Frame * AP_Win32Frame::buildFrame(XAP_Frame * pF) { AP_Win32Frame * pClone = static_cast(pF); if (pClone && pClone->initialize()) { const UT_Error error = pClone->_showDocument(); if (!error) { pClone->show(); return pClone; } } // clean up anything we created here if (pClone) { m_pWin32App->forgetFrame(pClone); delete pClone; } return 0; } HWND AP_Win32Frame::_createDocumentWindow(HWND hwndParent, UT_uint32 iLeft, UT_uint32 iTop, UT_uint32 iWidth, UT_uint32 iHeight) { // create the window(s) that the user will consider to be the // document window -- the thing between the bottom of the toolbars // and the top of the status bar. return the handle to it. // create a child window for us -- this will be the 'container'. // the 'container' will in turn contain the document window, the // rulers, and the variousscroll bars and other dead space. m_hwndContainer = CreateWindowEx(WS_EX_CLIENTEDGE, s_ContainerWndClassName, NULL, WS_CHILD | WS_VISIBLE, iLeft, iTop, iWidth, iHeight, hwndParent, NULL, m_pWin32App->getInstance(), NULL); UT_ASSERT(m_hwndContainer); SWL(m_hwndContainer, this); // now create all the various windows inside the container window. RECT r; GetClientRect(m_hwndContainer,&r); const int cyHScroll = GetSystemMetrics(SM_CYHSCROLL); const int cxVScroll = GetSystemMetrics(SM_CXVSCROLL); m_hWndHScroll = CreateWindowEx(0, "ScrollBar", 0, WS_CHILD | WS_VISIBLE | SBS_HORZ, 0, r.bottom - cyHScroll, r.right - cxVScroll, cyHScroll, m_hwndContainer, 0, m_pWin32App->getInstance(), 0); UT_ASSERT(m_hWndHScroll); SWL(m_hWndHScroll, this); m_hWndVScroll = CreateWindowEx(0, "ScrollBar", 0, WS_CHILD | WS_VISIBLE | SBS_VERT, r.right - cxVScroll, 0, cxVScroll, r.bottom - cyHScroll, m_hwndContainer, 0, m_pWin32App->getInstance(), 0); UT_ASSERT(m_hWndVScroll); SWL(m_hWndVScroll, this); #if 1 // if the StatusBar is enabled, our lower-right corner is a dead spot # define XX_StyleBits (WS_DISABLED | SBS_SIZEBOX) #else # define XX_StyleBits (SBS_SIZEGRIP) #endif m_hWndGripperHack = CreateWindowEx(0,"ScrollBar", 0, WS_CHILD | WS_VISIBLE | XX_StyleBits, r.right-cxVScroll, r.bottom-cyHScroll, cxVScroll, cyHScroll, m_hwndContainer, NULL, m_pWin32App->getInstance(), NULL); UT_ASSERT(m_hWndGripperHack); SWL(m_hWndGripperHack, this); // create the rulers, if needed int yTopRulerHeight = 0; int xLeftRulerWidth = 0; if (static_cast(m_pData)->m_bShowRuler) { _createRulers(); _getRulerSizes(yTopRulerHeight, xLeftRulerWidth); } // create a child window for us. m_hwndDocument = CreateWindowEx(0, s_DocumentWndClassName, NULL, WS_CHILD | WS_VISIBLE, xLeftRulerWidth, yTopRulerHeight, r.right - xLeftRulerWidth - cxVScroll, r.bottom - yTopRulerHeight - cyHScroll, m_hwndContainer, NULL, m_pWin32App->getInstance(), NULL); UT_ASSERT(m_hwndDocument); SWL(m_hwndDocument, this); return m_hwndContainer; } void AP_Win32Frame::_getRulerSizes(int &yTopRulerHeight, int &xLeftRulerWidth) { if (static_cast(m_pData)->m_pTopRuler) yTopRulerHeight = static_cast(m_pData)->m_pTopRuler->getHeight(); else yTopRulerHeight = 0; if (static_cast(m_pData)->m_pLeftRuler) xLeftRulerWidth = static_cast(m_pData)->m_pLeftRuler->getWidth(); else xLeftRulerWidth = 0; } void AP_Win32Frame::_createRulers(void) { _createTopRuler(); _createLeftRuler(); } void AP_Win32Frame::_createTopRuler(void) { RECT r; int cxVScroll, cyHScroll; GetClientRect(m_hwndContainer,&r); cxVScroll = GetSystemMetrics(SM_CXVSCROLL); cyHScroll = GetSystemMetrics(SM_CYHSCROLL); // create the top ruler AP_Win32TopRuler * pWin32TopRuler = new AP_Win32TopRuler(this); UT_ASSERT(pWin32TopRuler); m_hwndTopRuler = pWin32TopRuler->createWindow(m_hwndContainer, 0,0, (r.right - cxVScroll)); static_cast(m_pData)->m_pTopRuler = pWin32TopRuler; // get the width from the left ruler and stuff it into the top ruler. UT_uint32 xLeftRulerWidth = 0; if( m_hwndLeftRuler ) { AP_Win32LeftRuler * pWin32LeftRuler = NULL; pWin32LeftRuler = (AP_Win32LeftRuler *) static_cast(m_pData)->m_pLeftRuler; xLeftRulerWidth = pWin32LeftRuler->getWidth(); } pWin32TopRuler->setOffsetLeftRuler(xLeftRulerWidth); } void AP_Win32Frame::_createLeftRuler(void) { RECT r; int cxVScroll, cyHScroll; GetClientRect(m_hwndContainer,&r); cxVScroll = GetSystemMetrics(SM_CXVSCROLL); cyHScroll = GetSystemMetrics(SM_CYHSCROLL); UT_uint32 yTopRulerHeight = 0; if( m_hwndTopRuler ) { AP_Win32TopRuler * pWin32TopRuler = NULL; pWin32TopRuler = (AP_Win32TopRuler * ) static_cast(m_pData)->m_pTopRuler; yTopRulerHeight = pWin32TopRuler->getHeight(); } // create the left ruler AP_Win32LeftRuler * pWin32LeftRuler = new AP_Win32LeftRuler(this); UT_ASSERT(pWin32LeftRuler); m_hwndLeftRuler = pWin32LeftRuler->createWindow(m_hwndContainer,0,yTopRulerHeight, r.bottom - yTopRulerHeight - cyHScroll); static_cast(m_pData)->m_pLeftRuler = pWin32LeftRuler; // get the width from the left ruler and stuff it into the top ruler. if( m_hwndTopRuler ) { UT_uint32 xLeftRulerWidth = pWin32LeftRuler->getWidth(); AP_Win32TopRuler * pWin32TopRuler = NULL; pWin32TopRuler = (AP_Win32TopRuler * ) static_cast(m_pData)->m_pTopRuler; pWin32TopRuler->setOffsetLeftRuler(xLeftRulerWidth); } } UT_Error AP_Win32Frame::loadDocument(const char * szFilename, int ieft, bool createNew) { UT_ASSERT(UT_TODO); return UT_OK; } UT_Error AP_Win32Frame::loadDocument(const char * szFilename, int ieft) { UT_Vector vClones; XAP_App * pApp = getApp(); const bool bUpdateClones = (getViewNumber() > 0); if (bUpdateClones) { pApp->getClones(&vClones, this); } UT_Error err; err = _loadDocument(szFilename, (IEFileType) ieft); if (err) { // we could not load the document. // we cannot complain to the user here, we don't know // if the app is fully up yet. we force our caller // to deal with the problem. return err; } pApp->rememberFrame(this); if (bUpdateClones) { for (UT_uint32 i = 0; i < vClones.getItemCount(); i++) { AP_Win32Frame * pFrame = (AP_Win32Frame *) vClones.getNthItem(i); if(pFrame != this) { pFrame->_replaceDocument(m_pDoc); pApp->rememberFrame(pFrame, this); } } } return _showDocument(); } UT_Error AP_Win32Frame::_importDocument(const char * szFilename, int ieft, bool markClean) { UT_DEBUGMSG(("DOM: trying to import %s (%d, %d)\n", szFilename, ieft, markClean)); // are we replacing another document? if (m_pDoc) { // yep. first make sure it's OK to discard it, // TODO: query user if dirty... } // load a document into the current frame. // if no filename, create a new document. AD_Document * pNewDoc = new PD_Document(getApp()); UT_ASSERT(pNewDoc); if (!szFilename || !*szFilename) { pNewDoc->newDocument(); m_iUntitled = _getNextUntitledNumber(); goto ReplaceDocument; } UT_Error errorCode; errorCode = pNewDoc->importFile(szFilename, ieft, markClean); if (!errorCode) goto ReplaceDocument; UT_DEBUGMSG(("ap_Frame: could not open the file [%s]\n",szFilename)); UNREFP(pNewDoc); return errorCode; ReplaceDocument: getApp()->forgetClones(this); m_iUntitled = _getNextUntitledNumber(); // NOTE: prior document is discarded in _showDocument() m_pDoc = pNewDoc; return UT_OK; } UT_Error AP_Win32Frame::importDocument(const char * szFilename, int ieft, bool markClean) { bool bUpdateClones; UT_Vector vClones; XAP_App * pApp = getApp(); bUpdateClones = (getViewNumber() > 0); if (bUpdateClones) { pApp->getClones(&vClones, this); } UT_Error errorCode; errorCode = _importDocument(szFilename, (IEFileType) ieft, markClean); if (errorCode) { return errorCode; } pApp->rememberFrame(this); if (bUpdateClones) { for (UT_uint32 i = 0; i < vClones.getItemCount(); i++) { AP_Win32Frame * pFrame = (AP_Win32Frame *) vClones.getNthItem(i); if(pFrame != this) { pFrame->_replaceDocument(m_pDoc); pApp->rememberFrame(pFrame, this); } } } return _showDocument(); } void AP_Win32Frame::_scrollFuncY(void* pData, UT_sint32 yoff, UT_sint32 /*ylimit*/) { // this is a static callback function and doesn't have a 'this' pointer. // scroll event came in (probably from an EditMethod (like a PageDown // or insertData or something). update the on-screen scrollbar and // then warp the document window contents. AP_Win32Frame * pWin32Frame = static_cast(pData); UT_ASSERT(pWin32Frame); SCROLLINFO si = { 0 }; si.cbSize = sizeof(si); si.fMask = SIF_ALL; pWin32Frame->_getVerticalScrollInfo(&si); si.nPos = yoff; pWin32Frame->_setVerticalScrollInfo(&si); pWin32Frame->_getVerticalScrollInfo(&si); // values may have been clamped pWin32Frame->m_pView->setYScrollOffset(si.nPos); } void AP_Win32Frame::_scrollFuncX(void* pData, UT_sint32 xoff, UT_sint32 /*xlimit*/) { // this is a static callback function and doesn't have a 'this' pointer. AP_Win32Frame * pWin32Frame = static_cast(pData); UT_ASSERT(pWin32Frame); SCROLLINFO si = { 0 }; si.cbSize = sizeof(si); si.fMask = SIF_ALL; HWND hwndH = pWin32Frame->m_hWndHScroll; GetScrollInfo(hwndH, SB_CTL, &si); si.nPos = xoff; SetScrollInfo(hwndH, SB_CTL, &si, TRUE); GetScrollInfo(hwndH, SB_CTL, &si); // may have been clamped pWin32Frame->m_pView->setXScrollOffset(si.nPos); } /*****************************************************************/ #define SCROLL_LINE_SIZE 20 LRESULT CALLBACK AP_Win32Frame::_ContainerWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { AP_Win32Frame * f = GWL(hwnd); if (!f) { return DefWindowProc(hwnd, iMsg, wParam, lParam); } AV_View* pView = f->m_pView; switch (iMsg) { case WM_SETFOCUS: { SetFocus(f->m_hwndDocument); return 0; } case WM_SIZE: { const int nWidth = LOWORD(lParam); const int nHeight = HIWORD(lParam); f->_onSize(nWidth, nHeight); return 0; } case WM_VSCROLL: { int nScrollCode = (int) LOWORD(wParam); // scroll bar value SCROLLINFO si = { 0 }; si.cbSize = sizeof(si); si.fMask = SIF_ALL; f->_getVerticalScrollInfo(&si); switch (nScrollCode) { default: return 0; case SB_PAGEUP: si.nPos -= si.nPage; if (si.nPos < 0) si.nPos = 0; break; case SB_PAGEDOWN: si.nPos += si.nPage; break; case SB_LINEDOWN: si.nPos += SCROLL_LINE_SIZE; break; case SB_LINEUP: si.nPos -= SCROLL_LINE_SIZE; if (si.nPos < 0) si.nPos = 0; break; case SB_THUMBPOSITION: case SB_THUMBTRACK: si.nPos = (int)HIWORD(wParam); // dynamic scroll box position -- a 16-bit value si.nPos <<= f->m_vScale; break; } f->_setVerticalScrollInfo(&si); // notify window of new value. f->_getVerticalScrollInfo(&si); // update from window, in case we got clamped pView->sendVerticalScrollEvent(si.nPos); // now tell the view return 0; } case WM_HSCROLL: { int nScrollCode = (int) LOWORD(wParam); // scroll bar value int nPos = (int) HIWORD(wParam); // scroll box position SCROLLINFO si = { 0 }; si.cbSize = sizeof(si); si.fMask = SIF_ALL; GetScrollInfo(f->m_hWndHScroll, SB_CTL, &si); switch (nScrollCode) { case SB_PAGEUP: si.nPos -= si.nPage; if (si.nPos < 0) { si.nPos = 0; } SetScrollInfo(f->m_hWndHScroll, SB_CTL, &si, TRUE); break; case SB_PAGEDOWN: si.nPos += si.nPage; SetScrollInfo(f->m_hWndHScroll, SB_CTL, &si, TRUE); break; case SB_LINEDOWN: si.nPos += SCROLL_LINE_SIZE; SetScrollInfo(f->m_hWndHScroll, SB_CTL, &si, TRUE); break; case SB_LINEUP: si.nPos -= SCROLL_LINE_SIZE; if (si.nPos < 0) { si.nPos = 0; } SetScrollInfo(f->m_hWndHScroll, SB_CTL, &si, TRUE); break; case SB_THUMBPOSITION: case SB_THUMBTRACK: si.nPos = nPos; SetScrollInfo(f->m_hWndHScroll, SB_CTL, &si, TRUE); break; } if (nScrollCode != SB_ENDSCROLL) { // in case we got clamped GetScrollInfo(f->m_hWndHScroll, SB_CTL, &si); // now tell the view pView->sendHorizontalScrollEvent(si.nPos); } return 0; } case WM_SYSCOLORCHANGE: { SendMessage(f->m_hwndTopRuler,WM_SYSCOLORCHANGE,0,0); SendMessage(f->m_hwndLeftRuler,WM_SYSCOLORCHANGE,0,0); SendMessage(f->m_hwndDocument,WM_SYSCOLORCHANGE,0,0); return DefWindowProc(hwnd, iMsg, wParam, lParam); } case WM_MOUSEWHEEL: { // Get delta const int iDelta = (short) HIWORD(wParam); const int cWheelLines = GetMouseWheelLines(); if (WHEEL_PAGESCROLL == cWheelLines) { WORD wDir = (iDelta < 0) ? SB_PAGEDOWN : SB_PAGEUP; SendMessage(hwnd, WM_VSCROLL, MAKELONG(wDir, 0), NULL); } else { // Calculate the movement offset to an integer resolution const int iMove = (iDelta * cWheelLines) / WHEEL_DELTA; // Get current scroll position SCROLLINFO si = { 0 }; si.cbSize = sizeof(si); si.fMask = SIF_ALL; f->_getVerticalScrollInfo(&si); // Clip new position to limits int iNewPos = si.nPos - (iMove * SCROLL_LINE_SIZE); if (iNewPos > si.nMax) iNewPos = si.nMax; if (iNewPos < si.nMin) iNewPos = si.nMin; if (iNewPos != si.nPos) { // If position has changed set new position iNewPos >>= f->m_vScale; SendMessage(hwnd, WM_VSCROLL, MAKELONG(SB_THUMBPOSITION, iNewPos), NULL); } } } return 0; default: return DefWindowProc(hwnd, iMsg, wParam, lParam); } } void AP_Win32Frame::_onSize(int nWidth, int nHeight) { const int cyHScroll = GetSystemMetrics(SM_CYHSCROLL); const int cxVScroll = GetSystemMetrics(SM_CXVSCROLL); int yTopRulerHeight = 0; int xLeftRulerWidth = 0; _getRulerSizes(yTopRulerHeight, xLeftRulerWidth); MoveWindow(m_hWndVScroll, nWidth-cxVScroll, 0, cxVScroll, nHeight-cyHScroll, TRUE); MoveWindow(m_hWndHScroll, 0, nHeight-cyHScroll, nWidth - cxVScroll, cyHScroll, TRUE); MoveWindow(m_hWndGripperHack, nWidth-cxVScroll, nHeight-cyHScroll, cxVScroll, cyHScroll, TRUE); if (m_hwndTopRuler) { MoveWindow(m_hwndTopRuler, 0, 0, nWidth - cxVScroll, yTopRulerHeight, TRUE); InvalidateRect(m_hwndTopRuler, NULL, TRUE); } if (m_hwndLeftRuler) MoveWindow(m_hwndLeftRuler, 0, yTopRulerHeight, xLeftRulerWidth, nHeight - yTopRulerHeight - cyHScroll, TRUE); MoveWindow(m_hwndDocument, xLeftRulerWidth, yTopRulerHeight, nWidth - xLeftRulerWidth - cxVScroll, nHeight - yTopRulerHeight - cyHScroll, TRUE); } LRESULT CALLBACK AP_Win32Frame::_DocumentWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { AP_Win32Frame * f = GWL(hwnd); if (!f) { return DefWindowProc(hwnd, iMsg, wParam, lParam); } AV_View* pView = f->m_pView; EV_Win32Mouse* pMouse = (EV_Win32Mouse *) f->m_pMouse; switch (iMsg) { case WM_MOUSEACTIVATE: f->m_bMouseActivateReceived = true; return MA_ACTIVATE; case WM_SETFOCUS: if (pView) { pView->focusChange(AV_FOCUS_HERE); if (GetKeyState(VK_LBUTTON)>0) f->m_bFirstAfterFocus = true; if(!f->m_bMouseActivateReceived) { // HACK: Capture leaving a tool bar combo. // We need to get a mouse down signal. // windows is not activated so send a mouse down if the mouse is pressed. UT_DEBUGMSG(("%s(%d): Need to set mouse down\n", __FILE__, __LINE__)); // GetKeyState } } return 0; case WM_KILLFOCUS: if (pView) { pView->focusChange(AV_FOCUS_NONE); } return 0; case WM_CREATE: return 0; case WM_SETCURSOR: { FV_View * pFV = static_cast(pView); GR_Graphics * pG = pFV->getGraphics(); GR_Win32Graphics * pGWin32 = static_cast(pG); pGWin32->handleSetCursorMessage(); } return 1; case WM_LBUTTONDOWN: /* When we get the focus back */ if (f->m_bFirstAfterFocus) f->m_bFirstAfterFocus = false; else { if(GetFocus() != hwnd) { SetFocus(hwnd); pView = f->m_pView; pMouse = (EV_Win32Mouse *) f->m_pMouse; } pMouse->onButtonDown(pView,hwnd,EV_EMB_BUTTON1,wParam,LOWORD(lParam),HIWORD(lParam)); f->m_bMouseActivateReceived = false; } return 0; case WM_MBUTTONDOWN: f->_startTracking(LOWORD(lParam), HIWORD(lParam)); // pMouse->onButtonDown(pView,hwnd,EV_EMB_BUTTON2,wParam,LOWORD(lParam),HIWORD(lParam)); return 0; case WM_RBUTTONDOWN: pMouse->onButtonDown(pView,hwnd,EV_EMB_BUTTON3,wParam,LOWORD(lParam),HIWORD(lParam)); return 0; case WM_LBUTTONDBLCLK: pMouse->onDoubleClick(pView,hwnd,EV_EMB_BUTTON1,wParam,LOWORD(lParam),HIWORD(lParam)); return 0; case WM_MBUTTONDBLCLK: // pMouse->onDoubleClick(pView,hwnd,EV_EMB_BUTTON2,wParam,LOWORD(lParam),HIWORD(lParam)); return 0; case WM_RBUTTONDBLCLK: pMouse->onDoubleClick(pView,hwnd,EV_EMB_BUTTON3,wParam,LOWORD(lParam),HIWORD(lParam)); return 0; case WM_SYSKEYDOWN: case WM_KEYDOWN: { UT_DEBUGMSG(("WM_KEYDOWN %d - %d\n",wParam, lParam)); ev_Win32Keyboard *pWin32Keyboard = static_cast(f->m_pKeyboard); if (pWin32Keyboard->onKeyDown(pView,hwnd,iMsg,wParam,lParam)) return DefWindowProc(hwnd,iMsg,wParam,lParam); else return false; } case WM_SYSCHAR: case WM_CHAR: { UT_DEBUGMSG(("WM_CHAR %d - %d\n",wParam, lParam)); ev_Win32Keyboard *pWin32Keyboard = static_cast(f->m_pKeyboard); pWin32Keyboard->onChar(pView,hwnd,iMsg,wParam,lParam); return DefWindowProc(hwnd,iMsg,wParam,lParam); } case WM_IME_CHAR: { ev_Win32Keyboard *pWin32Keyboard = static_cast(f->m_pKeyboard); if (pWin32Keyboard->onIMEChar(pView,hwnd,iMsg,wParam,lParam)) return 0; return DefWindowProc(hwnd,iMsg,wParam,lParam); } case WM_MOUSEMOVE: if (f->_isTracking()) { f->_track(LOWORD(lParam),HIWORD(lParam)); } else { pMouse->onButtonMove(pView,hwnd,wParam,LOWORD(lParam),HIWORD(lParam)); } return 0; case WM_LBUTTONUP: if(GetFocus() != hwnd) // HACK: get focus back from tool bar combos. { SetFocus(hwnd); pView = f->m_pView; pMouse = (EV_Win32Mouse *) f->m_pMouse; pMouse->onButtonDown(pView,hwnd,EV_EMB_BUTTON1,wParam,LOWORD(lParam),HIWORD(lParam)); } pMouse->onButtonUp(pView,hwnd,EV_EMB_BUTTON1,wParam,LOWORD(lParam),HIWORD(lParam)); return 0; case WM_MBUTTONUP: f->_endTracking(LOWORD(lParam), HIWORD(lParam)); // pMouse->onButtonUp(pView,hwnd,EV_EMB_BUTTON2,wParam,LOWORD(lParam),HIWORD(lParam)); return 0; case WM_RBUTTONUP: pMouse->onButtonUp(pView,hwnd,EV_EMB_BUTTON3,wParam,LOWORD(lParam),HIWORD(lParam)); return 0; case WM_SIZE: { if (pView) { int nWidth = LOWORD(lParam); int nHeight = HIWORD(lParam); pView->setWindowSize(nWidth, nHeight); // may need to scroll to keep everything in sync. // the following is necessary to make sure that the // window de-scrolls as it gets larger. SCROLLINFO si = { 0 }; si.cbSize = sizeof(si); si.fMask = SIF_ALL; f->_getVerticalScrollInfo(&si); pView->sendVerticalScrollEvent(si.nPos,si.nMax-si.nPage); GetScrollInfo(f->m_hWndHScroll, SB_CTL, &si); pView->sendHorizontalScrollEvent(si.nPos,si.nMax-si.nPage); } return 0; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); UT_Rect r(ps.rcPaint.left,ps.rcPaint.top, ps.rcPaint.right-ps.rcPaint.left, ps.rcPaint.bottom-ps.rcPaint.top); pView->draw(&r); EndPaint(hwnd, &ps); return 0; } case WM_TIMER: { TIMERPROC * pfn = (TIMERPROC *)lParam; UT_ASSERT( (void *)(pfn) == (void *)(Global_Win32TimerProc) ); Global_Win32TimerProc(hwnd,WM_TIMER,(UINT)wParam,NULL); return 0; } case WM_DESTROY: return 0; case WM_INPUTLANGCHANGE: // let the XAP_Win32Frame handle this return ::SendMessage(f->m_hwndFrame, WM_INPUTLANGCHANGE, wParam, lParam); } /* switch (iMsg) */ return DefWindowProc(hwnd, iMsg, wParam, lParam); } /*****************************************************************/ bool AP_Win32Frame::initFrameData(void) { UT_ASSERT(!m_pData); AP_FrameData* pData = new AP_FrameData(m_pWin32App); m_pData = (void*) pData; return pData != 0; } void AP_Win32Frame::killFrameData(void) { AP_FrameData * pData = static_cast(m_pData); DELETEP(pData); m_pData = NULL; } UT_Error AP_Win32Frame::_loadDocument(const char * szFilename, IEFileType ieft) { // are we replacing another document? if (m_pDoc) { // yep. first make sure it's OK to discard it, // TODO: query user if document is changed... } // load a document into the current frame. // if no filename, create a new document. AD_Document * pNewDoc = new PD_Document(getApp()); UT_ASSERT(pNewDoc); if (!szFilename || !*szFilename) { pNewDoc->newDocument(); m_iUntitled = _getNextUntitledNumber(); } else { const UT_Error err = pNewDoc->readFromFile(szFilename, ieft); if (err) { UT_DEBUGMSG(("ap_Frame: could not open the file [%s]\n",szFilename)); UNREFP(pNewDoc); return err; } } getApp()->forgetClones(this); // NOTE: prior document is discarded in _showDocument() m_pDoc = pNewDoc; return UT_OK; } void AP_Win32Frame::translateDocumentToScreen(UT_sint32 &x, UT_sint32 &y) { // translate the given document mouse coordinates into absolute screen coordinates. POINT pt = { x, y }; ClientToScreen(m_hwndDocument,&pt); x = pt.x; y = pt.y; } HWND AP_Win32Frame::_createStatusBarWindow(HWND hwndParent, UT_uint32 iLeft, UT_uint32 iTop, UT_uint32 iWidth) { AP_Win32StatusBar * pStatusBar = new AP_Win32StatusBar(this); UT_ASSERT(pStatusBar); m_hwndStatusBar = pStatusBar->createWindow(hwndParent,iLeft,iTop,iWidth); static_cast(m_pData)->m_pStatusBar = pStatusBar; return m_hwndStatusBar; } void AP_Win32Frame::setStatusMessage(const char * szMsg) { static_cast(m_pData)->m_pStatusBar->setStatusMessage(szMsg); } UT_Error AP_Win32Frame::_replaceDocument(AD_Document * pDoc) { // NOTE: prior document is discarded in _showDocument() m_pDoc = REFP(pDoc); return _showDocument(); } void AP_Win32Frame::toggleRuler(bool bRulerOn) { toggleTopRuler( bRulerOn ); toggleLeftRuler( bRulerOn ); } void AP_Win32Frame::toggleTopRuler(bool bRulerOn) { AP_FrameData *pFrameData = static_cast(getFrameData()); UT_ASSERT(pFrameData); if (bRulerOn) { UT_ASSERT(!pFrameData->m_pTopRuler); _createTopRuler(); static_cast(m_pData)->m_pTopRuler->setView(m_pView, getZoomPercentage()); } else { // delete the actual widgets if (m_hwndTopRuler) DestroyWindow(m_hwndTopRuler); DELETEP(static_cast(m_pData)->m_pTopRuler); m_hwndTopRuler = NULL; } // repack the child windows RECT r; GetClientRect(m_hwndContainer, &r); _onSize(r.right - r.left, r.bottom - r.top); } void AP_Win32Frame::toggleLeftRuler(bool bRulerOn) { AP_FrameData *pFrameData = static_cast(getFrameData()); UT_ASSERT(pFrameData); if (bRulerOn) { // // If There is an old ruler just return // if(m_hwndLeftRuler) { return; } UT_ASSERT(!pFrameData->m_pLeftRuler); _createLeftRuler(); static_cast(m_pData)->m_pLeftRuler->setView(m_pView, getZoomPercentage()); } else { // delete the actual widgets if (m_hwndLeftRuler) DestroyWindow(m_hwndLeftRuler); DELETEP(static_cast(m_pData)->m_pLeftRuler); m_hwndLeftRuler = NULL; } // repack the child windows RECT r; GetClientRect(m_hwndContainer, &r); _onSize(r.right - r.left, r.bottom - r.top); } ///////////////////////////////////////////////////////////////////////// void AP_Win32Frame::_startTracking(UT_sint32 x, UT_sint32 y) { m_startMouseWheelY = y; m_bMouseWheelTrack = true; m_startScrollPosition = GetScrollPos(m_hWndVScroll, SB_CTL); SetCapture(m_hwndDocument); } void AP_Win32Frame::_endTracking(UT_sint32 x, UT_sint32 y) { m_bMouseWheelTrack = false; ReleaseCapture(); } void AP_Win32Frame::_track(UT_sint32 x, UT_sint32 y) { UT_sint32 Delta = y - m_startMouseWheelY; // map delta to scroll bar range. int iMin, iMax; RECT rect; GetClientRect(m_hwndDocument, &rect); if(y < rect.top || y > rect.bottom) return; GetScrollRange(m_hWndVScroll, SB_CTL, &iMin, &iMax); if(Delta < 0) { int iNewPosition = (m_startScrollPosition - iMin) * (y - rect.top) / (m_startMouseWheelY - rect.top); SendMessage(m_hwndContainer, WM_VSCROLL, MAKEWPARAM(SB_THUMBTRACK, (WORD)iNewPosition), NULL); } else { int iNewPosition = m_startScrollPosition + (iMax - m_startScrollPosition) * (y - m_startMouseWheelY) / (rect.bottom - m_startMouseWheelY); SendMessage(m_hwndContainer, WM_VSCROLL, MAKEWPARAM(SB_THUMBTRACK, (WORD)iNewPosition), NULL); } } void AP_Win32Frame::toggleBar(UT_uint32 iBarNb, bool bBarOn) { UT_DEBUGMSG(("AP_Win32Frame::toggleBar %d, %d\n", iBarNb, bBarOn)); // TMN: Yes, this cast is correct. We store EV_Win32Toolbar in // m_vecToolbars, but we only need the EV_Toolbar part of it. EV_Toolbar* pToolbar = (EV_Toolbar*)m_vecToolbars.getNthItem(iBarNb); UT_ASSERT(pToolbar); if (!pToolbar) // release build paranoia { return; } if (bBarOn) { pToolbar->show(); } else { pToolbar->hide(); } int iToolbarCount = 0; for (UT_uint32 i = 0; i < m_vecToolbarLayoutNames.getItemCount(); i++) { EV_Win32Toolbar *pThisToolbar = (EV_Win32Toolbar *)m_vecToolbars.getNthItem(i); UT_ASSERT(pThisToolbar); if (pThisToolbar) // release build paranoia if ( pThisToolbar->bVisible() ) iToolbarCount++; } if( !iToolbarCount || ((iToolbarCount == 1) && bBarOn) ) { RECT r; ShowWindow( m_hwndRebar, (iToolbarCount ? SW_SHOW : SW_HIDE) ); MoveWindow(m_hwndRebar, 0, 0, (iToolbarCount ? m_iSizeWidth : 1), (iToolbarCount ? m_iSizeHeight : 1), TRUE); if( iToolbarCount ) { GetClientRect(m_hwndRebar, &r); m_iBarHeight = r.bottom - r.top + 6; } else m_iBarHeight = 1; GetClientRect(m_hwndContainer, &r); _onSize(r.right - r.left, r.bottom - r.top); } // We *need* to make the window recalc its layout after adding/removing a // toolbar in the rebar control. Since we have no "recalcLayout" I'm // aware of we use this not-so-good-but-old idiom of resizing the window. RECT rc; GetWindowRect(m_hwndFrame, &rc); const int cx = rc.right - rc.left; const int cy = rc.bottom - rc.top; const UINT fFlags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER; SetWindowPos(m_hwndFrame, 0, 0, 0, cx - 1, cy - 1, fFlags | SWP_NOREDRAW); SetWindowPos(m_hwndFrame, 0, 0, 0, cx, cy, fFlags); } void AP_Win32Frame::toggleStatusBar(bool bStatusBarOn) { AP_FrameData *pFrameData = static_cast(getFrameData()); UT_ASSERT(pFrameData); if (bStatusBarOn) { pFrameData->m_pStatusBar->show(); } else { pFrameData->m_pStatusBar->hide(); } UpdateWindow(m_hwndContainer); } void AP_Win32Frame::_showOrHideToolbars(void) { bool *bShowBar = static_cast (m_pData)->m_bShowBar; for (UT_uint32 i = 0; i < m_vecToolbarLayoutNames.getItemCount(); i++) { if (!bShowBar[i]) toggleBar( i, false ); } } void AP_Win32Frame::_showOrHideStatusbar(void) { bool bShowStatusBar = static_cast (m_pData)->m_bShowStatusBar; toggleStatusBar(bShowStatusBar); }