extern pascal OSStatus GetDetachedIconSuite(IconSuiteRef *theIconSuite, SInt16 theResID, IconSelectorValue selector)
	// See comment in interface part.
{
	long oldA4;
	OSStatus err;
	THz oldZone;
	
	oldA4 = SetUpA4();
	
	assert(theIconSuite != NULL);
	
	oldZone = SetSystemZone();

	// The algorithm here is perfectly simple.  First get the icon suite,
	// then iterate over its contents detaching each handle.  I looked
	// at the Icon Services code and this seems like a perfectly reasonable
	// strategy.  It also disassembled SBGetDetachIconSuite and it works
	// in the same way.
	
	err = GetIconSuite(theIconSuite, theResID, selector);
	if (err == noErr) {
		(void) ForEachIconDo(*theIconSuite, kSelectorAllAvailableData, gDetachIconActionUPP, NULL);
	}
	
	SetZone(oldZone);
	
	(void) SetA4(oldA4);
	
	return err;
}
Esempio n. 2
0
/*--------------------------------------------------------------------
 * DESCRIPTION
 *      Do progress callback. - MAC version
 *
 * AUTHOR
 *      mec
 *
 * DATE CREATED
 *      May 4, 1995
 *------------------------------------------------------------------*/
static SpStatus_t SpDoIter (
			SpTagIter_t	ProgressFunc,
			SpIterState_t	State,
			SpProfile_t	Profile,
			SpTagId_t	TagId,
			void		FAR *Data)
{
#if defined(KPMAC68K)
	volatile long	hostA4, hostA5;
	volatile long	thisA4, thisA5;
#endif
	SpStatus_t	status;
 
	if (NULL == ProgressFunc)
		return SpStatSuccess;
 
#if defined(KPMAC68K)
	/* restore host's global world - we don't know if its an A4 or A5*/
	SPretrieveCallbackA4A5(&hostA4, &hostA5);
	if (hostA5 != 0)
		thisA5 = SetA5(hostA5);
	if (hostA4 != 0)
		thisA4 = SetA4(hostA4);
#endif
 
	status = CallSPIterCallBackFunc((spIterCallBackUPP)ProgressFunc,
					State, Profile, TagId, Data);
 
#if defined (KPMAC68K)
	/* reset our global world */
	if (hostA5 != 0)
		SetA5(thisA5);
	if (hostA4 != 0)
		SetA4(thisA4);
#endif
 
	return status;
}
static pascal void InsertMenuPatch(MenuHandle theMenu, SInt16 beforeID)
	// This is our patch on InsertMenu.  The only goal of this
	// patch is to watch for the first person to insert a system
	// menu and then, when they do that, turn around and insert
	// our system menus along with it.  This patch typically
	// executes at Process Manager startup time as the Help menu
	// is inserted.  The nice thing about this is that we don't
	// have to monkey with the system state so that our menus
	// go into the system menu list; the system has already done
	// that, our menus just tag along for the ride.
{
	long oldA4;
	
	oldA4 = SetUpA4();
	
	// Our patch should only be installed if InitMoreSystemMenus was successful.
	assert(gRootSysMenus != NULL);
	
	CallInsertMenuProc(gInsertMenuOldUPP, theMenu, beforeID);
	
	if ( !gHaveInsertedRootSysMenus && IsSystemMenuID( (**theMenu).menuID ) ) {

		// Remember the system's MenuCInfo in gRootSysMenuCInfo
		// so that we can set it back later.  We currently
		// don't use this information but I have a feeling
		// we'll need it in the future.
		
		gRootSysMenuCInfo = LMGetMenuCInfo();
		
		// Insert our menus into the system menu list.
		
		InsertMySystemMenus((**theMenu).menuID);
		
		// We only try to do this once.  If we fail, too bad,
		// there's no one to report an error to.
		
		gHaveInsertedRootSysMenus = true;
	}

	(void) SetA4(oldA4);
}
extern pascal OSStatus InsertSystemMenu(MenuRef theMenu,
										SystemMenuCallbackProc callback,
										void *refcon)
	// See comment in interface part.
{
	long oldA4;
	OSStatus err;
	RootSysMenuEntry newEntry;
	
	oldA4 = SetUpA4();

	assert(ValidateSystemMenuRef(theMenu));
	assert(callback != NULL);

	// If either of these fire, you're too late to call this routine,
	// either because system startup is complete or because someone
	// has already inserted a system menu.

	assert( IsSystemStartup() );
	assert( ! gHaveInsertedRootSysMenus );

	// Fill out the new entry.
	
	newEntry.theMenu  = theMenu;
	newEntry.callback = callback;
	newEntry.refcon   = refcon;
	
	// Add the entry on to the system menu list.  Later on, in the
	// InsertMenuPatch, we'll add it to the menu bar.
	
	if (theMenu == NULL || callback == NULL) {
		err = paramErr;
	} else {
		err = PtrAndHand(&newEntry, (Handle) gRootSysMenus, sizeof(newEntry));
	}

	(void) SetA4(oldA4);
	
	return err;
}
Esempio n. 5
0
		~IASGlobalContext() 
		{
			SetA4(saveA4);					// Set A4 back.
		}
extern pascal OSStatus InsertSystemSubMenu(MenuRef rootMenu,
										MenuRef parentMenu, UInt16 itemInParent, MenuRef childMenu)
	// See comment in interface part.
{
	long oldA4;
	OSStatus err;
	SubSysMenuEntry newEntry;
	SInt16 newIDForChildMenu;
	
	oldA4 = SetUpA4();

	assert(ValidateSystemMenuRef(rootMenu  ));
	assert(ValidateSystemMenuRef(parentMenu));
	assert(ValidateSystemMenuRef(childMenu ));
	
	assert(gMenuSelectState = kMenuSelectStatePre);
	
	// Validate parameters
	
	err = noErr;
	if ((rootMenu == NULL) || (parentMenu == NULL) || (childMenu == NULL)) {
		err = paramErr;
	}
	if (err == noErr && ((itemInParent == 0) || (itemInParent > CountMenuItems(parentMenu)))) {
		err = paramErr;
	}

	// Make sure rootMenu references a current system menu.
	// If it does, record the index of the root menu for
	// later use by HandleMenuSelect.  Also fill out the rest
	// of the fields of the sub-menu entry.

	if (err == noErr) {
		newEntry.rootMenuIndex = FindRootMenuByRef(rootMenu);
		newEntry.parentMenu    = parentMenu;
		newEntry.itemInParent  = itemInParent;
		newEntry.childMenu     = childMenu;
		
		if (newEntry.rootMenuIndex == kRootMenuNotFound) {
			err = paramErr;
		}
	}
	
	// Add newEntry to the sub-menu list, creating the sub-menu list if necessary.

	if (err == noErr) {
		if (gSubSysMenus == NULL) {
			gSubSysMenus = (SubSysMenuHandle) NewHandleSys(0);
			err = MemError();
		}
	}
	if (err == noErr) {
		err = PtrAndHand(&newEntry, (Handle) gSubSysMenus, sizeof(newEntry));
	}
	
	// Finally, insert the menu with a unique ID into the menu bar,
	// and set the parent item to reference its ID.
	
	if (err == noErr) {
		newIDForChildMenu = FindUniqueSubMenuID();
		(**childMenu).menuID = newIDForChildMenu;
		InsertMenu(childMenu, hierMenu);

		SetItemCmd(parentMenu, itemInParent, hMenuCmd);
		SetItemMark(parentMenu, itemInParent, newIDForChildMenu);
		
		// I added this after testing revealed that adding a sub-menu didn't 
		// force the menu size to be recalculated, so the item text of the
		// hierarchical item in the sub-menu was being truncated.  This
		// only appears to happen on Mac OS 8.5, but the fix is sufficiently
		// benign to be employed on all systems.
		
		CalcMenuSize(parentMenu);
	}
	
	(void) SetA4(oldA4);
	
	return err;
}
static pascal SInt32 MenuSelectPatch(Point startPt)
	// This is our patch on MenuSelect.  The basic idea is to
	// call our clients to let them adjust their menus (and install
	// sub-menus by calling InsertSystemMenu), call through to
	// the old trap, call our clients to un-adjust their menus,
	// and then call HandleMenuSelect to see whether the chosen
	// menu was one of our system menus.  If it was, HandleMenuSelect
	// calls the client to tell them that their menu was chosen and
	// returns 0 so that we tell the host application that nothing
	// happened.
	//
	// Note that MenuSelect is called by MenuEvent, so this patch
	// covers that case as well.
{
	long oldA4;
	SInt32 result;
	SubSysMenuHandle tempSubSysMenus;
	
	oldA4 = SetUpA4();
	
	// Our patch should only be installed if InitMoreSystemMenus was successful.
	assert(gRootSysMenus != NULL);

	// Only do stuff if we're actually up and running.
	// If gHaveInsertedRootSysMenus is false, it means that
	// someone is calling MenuSelect before our InsertMenu patch
	// has run, ie before anyone has inserted any system menus,
	// ie before the Process Manager has launched.  I don't know
	// whether this ever happens, I'm use being cautious.
	
	// Also, if gMenuSelectState is not NULL then we're getting recursion
	// where we're not expecting it (probably from the kSystemMenuPreSelectAdjust
	// or kSystemMenuPostSelectAdjust callbacks, but possibly from another
	// trap patch), so we just call through to the system in that case.
	
	// We want debug versions to tell the client that they're recursing
	// in an unsupport fashion.
	
	assert(gMenuSelectState == kMenuSelectStateNil);
	
	if ( gHaveInsertedRootSysMenus && gMenuSelectState == kMenuSelectStateNil) {
	
		// OK, so we're up and running, so let's do our stuff.
		
		// First tell all clients that we're about to do a MenuSelect
		// (they can adjust their menus and insert sub-menus)...
		
		assert(gSubSysMenus == NULL);
		gMenuSelectState = kMenuSelectStatePre;
		CallAllClients(kSystemMenuPreSelectAdjust, NULL);
		
		// ... then call through to the old trap address...
		
		result = CallMenuSelectProc(gMenuSelectOldUPP, startPt);
		
		// ... and then tell all clients that we're done...
		
		gMenuSelectState = kMenuSelectStatePost;
		CallAllClients(kSystemMenuPostSelectAdjust, NULL);
		
		// Things get tricky here.  In order to allow the client
		// to post modal dialogs from its kSystemMenuActOnChosen callback,
		// we must be re-entrant at the time we call HandleMenuSelect
		// (because the ModalDialog routine will call MenuSelect).
		// But we want to avoid having sub-menus in the menu bar when
		// we're recursively called because we're going to call the
		// client's kSystemMenuPreSelectAdjust callback, which will
		// attempt to re-insert those menus.
		//
		// So, we remove our sub-menus now, before calling the
		// kSystemMenuActOnChosen callback, then we make the callback,
		// and then we dispose of the memory we used to track the
		// sub-menus.
		
		tempSubSysMenus = gSubSysMenus;
		gSubSysMenus = NULL;
		
		DeleteSubMenus(tempSubSysMenus);

		gMenuSelectState = kMenuSelectStateNil;

		// At this point we're prepared to accept recursion.
		// Call HandleMenuSelect to process the results
		// from the menu operation and call the appropriate
		// client if it was one of our menus.
		
		result = HandleMenuSelect(result, tempSubSysMenus);

		// Clean up.  If we created any sub-menu info,
		// dispose of it.
		
		if (tempSubSysMenus != NULL) {
			DisposeHandle( (Handle) tempSubSysMenus);
			assert(MemError() == noErr);
		}
	} else {
		result = CallMenuSelectProc(gMenuSelectOldUPP, startPt);
	}

	assert(gMenuSelectState == kMenuSelectStateNil);

	(void) SetA4(oldA4);
	
	return result;
}