/* AbiSource Application Framework * Copyright (C) 1998 AbiSource, Inc. * Copyright (C) 1999 John Brewer DBA Jera Design * * 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. */ /* Platform: MacOS Classic & Carbon $Id$ */ #include /* MacOS includes */ #ifndef XP_MAC_TARGET_QUARTZ # include #endif #include #include #include #include #include #include #include #ifdef XP_MAC_TARGET_MACOSX # include #endif /* end */ #include "ut_string.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include "ut_MacFiles.h" #include "xap_Args.h" #include "xap_MacApp.h" #include "xap_MacClipboard.h" #include "xap_MacFrame.h" #include "xap_MacFontManager.h" #include "xap_MacTlbr_Icons.h" #include "xap_MacTlbr_ControlFactory.h" #include "xap_MacToolbar_Control.h" #include "ev_MacMenu.h" bool XAP_MacApp::m_NotInitialized = true; /*****************************************************************/ XAP_MacApp::XAP_MacApp(XAP_Args * pArgs, const char * szAppName) : XAP_App(pArgs, szAppName), m_dialogFactory(this), m_controlFactory() { if (m_NotInitialized) { InitializeMacToolbox (); } m_finished = false; m_pMacToolbarIcons = 0; m_pMacFontManager = NULL; m_pToolbarControl = new XAP_MacToolbar_Control (); } XAP_MacApp::~XAP_MacApp(void) { DELETEP(m_pMacFontManager); DELETEP(m_pMacToolbarIcons); DELETEP(m_pToolbarControl); } bool XAP_MacApp::initialize(void) { OSStatus err; // let our base class do it's thing. XAP_App::initialize(); if (!_loadFonts()) return false; // load only one copy of the platform-specific icons. m_pMacToolbarIcons = new AP_MacToolbar_Icons(); // do anything else we need here... // _pClipboard = new AP_MacClipboard(); #if defined(USE_CARBON_EVENTS) EventTypeSpec eventTypes[1]; eventTypes[0].eventClass = kEventClassCommand; eventTypes[0].eventKind = kEventCommandProcess; EventHandlerRef handlerRef; EventHandlerUPP handlerUPP = NewEventHandlerUPP (HandleCarbonMenus); err = ::InstallApplicationEventHandler (handlerUPP, 1, eventTypes, (void*)this, &handlerRef); #endif m_pToolbarControl->show (); return true; } void XAP_MacApp::reallyExit(void) { ExitToShell(); } UT_sint32 XAP_MacApp::makeDirectory(const char * szPath, const UT_sint32 mode ) const { /* FIXME: make this return something real. The Unix version looks like this: return mkdir(szPath, mode); */ return 0; } XAP_DialogFactory * XAP_MacApp::getDialogFactory(void) { return &m_dialogFactory; } XAP_Toolbar_ControlFactory * XAP_MacApp::getControlFactory(void) { return &m_controlFactory; } const char * XAP_MacApp::getUserPrivateDirectory(void) { /* return a pointer to a static buffer */ short vRefNum; long dirID; FSSpec dirSpec; OSErr err; Handle fullPath = NULL; short fpLen = 0; #ifndef PATH_MAX #define PATH_MAX 4096 #endif static char buf[PATH_MAX]; // memset(buf,0,sizeof(buf)); buf [0] = 0; /* change this later as MacOS don't really have user dir. use prefs dir instead */ ::FindFolder (kOnSystemDisk, kPreferencesFolderType, true, &vRefNum, &dirID); err = ::FSMakeFSSpec (vRefNum, dirID, "\p", &dirSpec); UT_ASSERT (err == noErr); err = ::FSpGetFullPath (&dirSpec, &fpLen, &fullPath); UT_ASSERT (err == noErr); UT_ASSERT (fullPath != NULL); ::HLock (fullPath); strncpy (buf, (char *)*fullPath, PATH_MAX); buf [fpLen] = 0; ::HUnlock (fullPath); ::DisposeHandle (fullPath); fullPath = NULL; /* TODO: check buffer */ strcat (buf, ":AbiSuite"); return buf; } bool XAP_MacApp::_loadFonts (void) { m_pMacFontManager = new XAP_MacFontManager(); UT_ASSERT(m_pMacFontManager); return true; } UT_uint32 XAP_MacApp::_getExeDir(char* /*pDirBuf*/, UT_uint32 /*iBufLen*/) { UT_ASSERT (UT_NOT_IMPLEMENTED); return 0; } void XAP_MacApp::InitializeMacToolbox () { OSStatus err; if (m_NotInitialized) { // This is REALLY the first thing to do // Even before any other Initialization. Note that this this is MacOS dependant // and application independent. #if XP_MAC_TARGET_CLASSIC // Initialize the Toolbox in Classic API ::InitGraf(&qd.thePort); // Toolbox Managers ::InitFonts(); ::InitWindows(); ::InitMenus(); ::TEInit(); ::InitDialogs(nil); ::MaxApplZone(); ::MoreMasters (); ::MoreMasters (); ::MoreMasters (); ::MoreMasters (); #endif #if XP_MAC_TARGET_CARBON ::MoreMasterPointers (4); #endif err = ::RegisterAppearanceClient (); m_NotInitialized = false; } } #if defined(USE_CARBON_EVENTS) /*! Carbon event handler */ pascal OSStatus XAP_MacApp::HandleCarbonMenus (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) { OSStatus err = noErr; XAP_MacApp * myApp = (XAP_MacApp *)userData; UT_ASSERT (myApp); UInt32 eventKind; HICommand cmd; eventKind = ::GetEventKind (theEvent); if (eventKind == kEventCommandProcess) { XAP_Menu_Id xapId; GetEventParameter (theEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof (HICommand), NULL, &cmd); xapId = cmd.commandID; XAP_MacFrame *theFrame = dynamic_cast(myApp->getLastFocussedFrame ()); UT_ASSERT (theFrame); EV_MacMenu *menu = theFrame->getMenu(); UT_ASSERT (menu); menu->onCommand (xapId); } err = CallNextEventHandler (nextHandler, theEvent); return err; } #else /*! Dispatch the event. Classic events only */ void XAP_MacApp::DispatchEvent (const EventRecord & theEvent) { WindowPtr targetWin; short winLocation; XAP_MacFrame *frame = NULL; long menuSelection; switch (theEvent.what) { case keyDown: menuSelection = ::MenuEvent (&theEvent); if (HiWord (menuSelection != 0)) { HandleMenus (menuSelection); } else { // TODO handle key events } break; case mouseDown: winLocation = ::FindWindow(theEvent.where, &targetWin); #if defined(XP_MAC_TARGET_CARBON) && XP_MAC_TARGET_CARBON if (::GetWindowKind(targetWin) == XAP_MACFRAME_WINDOW_KIND) { frame = (XAP_MacFrame*)GetWRefCon(targetWin); #else if (((WindowRecord *)targetWin)->windowKind == XAP_MACFRAME_WINDOW_KIND) { frame = (XAP_MacFrame*)((WindowRecord *)targetWin)->refCon; #endif } switch (winLocation) { case inMenuBar: HandleMenus (::MenuSelect(theEvent.where)); break; case inSysWindow: #if defined(XP_MAC_TARGET_CARBON) && XP_MAC_TARGET_CARBON #else ::SystemClick (&theEvent, targetWin); #endif break; case inContent: if (frame != NULL) { frame->raise (); } else { ::BringToFront (targetWin); } break; case inDrag: ::DragWindow (targetWin, theEvent.where, #if defined(XP_MAC_TARGET_CARBON) && XP_MAC_TARGET_CARBON NULL /* valid only for Carbon 1.0 and forward */ #else &qd.screenBits.bounds #endif ); /* TODO handle multiple screens */ break; case inGrow: { long newSize = ::GrowWindow (targetWin, theEvent.where, #if defined(XP_MAC_TARGET_CARBON) && XP_MAC_TARGET_CARBON NULL /* valid only for Carbon 1.0 and forward */ #else &qd.screenBits.bounds #endif ); ::SizeWindow (targetWin, LoWord (newSize), HiWord (newSize), true); if (frame != NULL) { frame->_macGrow (); } } break; case inGoAway: if (::TrackGoAway (targetWin, theEvent.where)) { if (frame != NULL) { frame->close (); } } break; case inProxyIcon: // TODO handle proxy icons break; case inZoomIn: case inZoomOut: if (::TrackBox (targetWin, theEvent.where, winLocation)) { if (frame != NULL) { } } break; } break; case updateEvt: targetWin = *((WindowPtr*) &theEvent.message); #if defined(XP_MAC_TARGET_CARBON) && XP_MAC_TARGET_CARBON if (::GetWindowKind(targetWin) == XAP_MACFRAME_WINDOW_KIND) { frame = (XAP_MacFrame*)GetWRefCon(targetWin); #else if (((WindowRecord *)targetWin)->windowKind == XAP_MACFRAME_WINDOW_KIND) { frame = (XAP_MacFrame*)((WindowRecord *)targetWin)->refCon; #endif } if (frame != NULL) { frame->_macUpdate (); } break; case kHighLevelEvent: ::AEProcessAppleEvent (&theEvent); break; } } /* Classic events only */ void XAP_MacApp::HandleMenus (long menuSelection) { short id, item; id = HiWord (menuSelection); item = LoWord (menuSelection); if (id != 0) { XAP_MacFrame *theFrame = dynamic_cast(getLastFocussedFrame ()); UT_ASSERT (theFrame); EV_MacMenu *menu = theFrame->getMenu(); UT_ASSERT (menu); XAP_Menu_Id xapId = menu->findMenuId (id, item); menu->onCommand (xapId); } HiliteMenu(0); } #endif /* Run the main event loop. */ void XAP_MacApp::run () { unsigned short mask = everyEvent; EventRecord theEvent; unsigned long delay = ::GetCaretTime(); #if defined(USE_CARBON_EVENTS) RunApplicationEventLoop (); #else while (!m_finished) { while (::WaitNextEvent(mask, &theEvent, delay, NULL)) { DispatchEvent (theEvent); } } #endif }