First stab at Cocoa impl of widget. Some code still carbon, copied from

widget/src/mac. [Not part of build].
This commit is contained in:
pinkerton%netscape.com 2001-11-06 15:35:24 +00:00
Родитель 18c0c3636f
Коммит 43eb937819
39 изменённых файлов: 15495 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,69 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// nsAppShellCocoa
//
// This file contains the default interface of the application shell. Clients
// may either use this implementation or write their own. If you write your
// own, you must create a message sink to route events to. (The message sink
// interface may change, so this comment must be updated accordingly.)
//
#ifndef nsAppShellCocoa_h__
#define nsAppShellCocoa_h__
#include "nsIAppShell.h"
class nsAppShellCocoa : public nsIAppShell
{
public:
nsAppShellCocoa();
virtual ~nsAppShellCocoa();
NS_DECL_ISUPPORTS
NS_DECL_NSIAPPSHELL
private:
};
#endif // nsAppShellCocoa_h__

Просмотреть файл

@ -0,0 +1,204 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// nsAppShellCocoa
//
// This file contains the default implementation of the application shell. Clients
// may either use this implementation or write their own. If you write your
// own, you must create a message sink to route events to. (The message sink
// interface may change, so this comment must be updated accordingly.)
//
#undef DARWIN
#import <Cocoa/Cocoa.h>
#include "nsAppShellCocoa.h"
NS_IMPL_THREADSAFE_ISUPPORTS1(nsAppShellCocoa, nsIAppShell)
//-------------------------------------------------------------------------
//
// nsAppShellCocoa constructor
//
//-------------------------------------------------------------------------
nsAppShellCocoa::nsAppShellCocoa()
{
NS_INIT_REFCNT();
}
//-------------------------------------------------------------------------
//
// nsAppShellCocoa destructor
//
//-------------------------------------------------------------------------
nsAppShellCocoa::~nsAppShellCocoa()
{
}
//-------------------------------------------------------------------------
//
// Create the application shell
//
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsAppShellCocoa::Create(int* argc, char ** argv)
{
// There's reallly not a whole lot that needs to be done here. The
// window will register its own interest in the necessary events
// so there's no need for us to create a pump or a sink.
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Enter a message handler loop
//
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsAppShellCocoa::Run(void)
{
[NSApp run];
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Exit appshell
//
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsAppShellCocoa::Exit(void)
{
[NSApp stop];
return NS_OK;
}
NS_IMETHODIMP
nsAppShellCocoa::SetDispatchListener(nsDispatchListener* aDispatchListener)
{
// nobody uses this except viewer
return NS_OK;
}
//-------------------------------------------------------------------------
//
// respond to notifications that an event queue has come or gone
//
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsAppShellCocoa::ListenToEventQueue(nsIEventQueue * aQueue, PRBool aListen)
{
// unnecessary; handled elsewhere
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Prepare to process events
//
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsAppShellCocoa::Spinup(void)
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Stop being prepared to process events.
//
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsAppShellCocoa::Spindown(void)
{
return NS_OK;
}
//
// GetNativeEvent
// DispatchNativeEvent
//
// These are generally used in the tight loop of a modal event loop. Cocoa
// has other ways of dealing with this, perhaps those should be investigated
// here.
//
NS_METHOD
nsAppShellCocoa::GetNativeEvent(PRBool &aRealEvent, void *&aEvent)
{
NS_WARNING("GetNativeEvent NOT YET IMPLEMENTED");
#if 0
static EventRecord theEvent; // icky icky static (can't really do any better)
if (!mMacPump.get())
return NS_ERROR_NOT_INITIALIZED;
aRealEvent = mMacPump->GetEvent(theEvent);
aEvent = &theEvent;
#endif
return NS_OK;
}
NS_METHOD
nsAppShellCocoa::DispatchNativeEvent(PRBool aRealEvent, void *aEvent)
{
NS_WARNING("DispatchNativeEvent NOT YET IMPLEMENTED");
#if 0
if (!mMacPump.get())
return NS_ERROR_NOT_INITIALIZED;
mMacPump->DispatchEvent(aRealEvent, (EventRecord *) aEvent);
#endif
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is IBM code.
*
* The Initial Developer of the Original Code is IBM.
* Portions created by IBM are
* Copyright (C) International Business Machines
* Corporation, 2000. All Rights Reserved.
*
* Contributor(s): Simon Montagu
*/
#include "nsBidiKeyboard.h"
NS_IMPL_ISUPPORTS1(nsBidiKeyboard, nsIBidiKeyboard)
nsBidiKeyboard::nsBidiKeyboard() : nsIBidiKeyboard()
{
NS_INIT_REFCNT();
}
nsBidiKeyboard::~nsBidiKeyboard()
{
}
NS_IMETHODIMP nsBidiKeyboard::IsLangRTL(PRBool *aIsRTL)
{
*aIsRTL = PR_FALSE;
#ifdef IBMBIDI
// XXX Insert platform specific code to determine keyboard direction
#endif
return NS_OK;
}
NS_IMETHODIMP nsBidiKeyboard::SetLangFromBidiLevel(PRUint8 aLevel)
{
#ifdef IBMBIDI
// XXX Insert platform specific code to set keyboard language
#endif
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is IBM code.
*
* The Initial Developer of the Original Code is IBM.
* Portions created by IBM are
* Copyright (C) International Business Machines
* Corporation, 2000. All Rights Reserved.
*
* Contributor(s): Simon Montagu
*/
#ifndef __nsBidiKeyboard
#define __nsBidiKeyboard
#include "nsIBidiKeyboard.h"
class nsBidiKeyboard : public nsIBidiKeyboard
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIBIDIKEYBOARD
nsBidiKeyboard();
virtual ~nsBidiKeyboard();
/* additional members */
};
#endif // __nsBidiKeyboard

Просмотреть файл

@ -0,0 +1,266 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef Window_h__
#define Window_h__
#include "nsISupports.h"
#include "nsBaseWidget.h"
#include "nsDeleteObserver.h"
#include "nsIWidget.h"
#include "nsIKBStateControl.h"
#include "nsIAppShell.h"
#include "nsIMouseListener.h"
#include "nsIEventListener.h"
#include "nsString.h"
#include "nsIMenuBar.h"
#include "nsplugindefs.h"
#include <QuickDraw.h>
#define NSRGB_2_COLOREF(color) \
RGB(NS_GET_R(color),NS_GET_G(color),NS_GET_B(color))
struct nsPluginPort;
#undef DARWIN
#import <Cocoa/Cocoa.h>
class nsChildView;
class nsIEventSink;
@interface ChildView : NSQuickDrawView
{
// the nsChildView that created the view. It retains this NSView, so
// the link back to it must be weak.
nsChildView* mGeckoChild;
// allows us to redispatch events back to a centralized location
nsIEventSink* mEventSink;
// tag for our mouse enter/exit tracking rect
NSTrackingRectTag mMouseEnterExitTag;
}
// sets up our view, attaching it to its owning gecko view
- (id) initWithGeckoChild:(nsChildView*)child eventSink:(nsIEventSink*)sink;
// access the nsIWidget associated with this view. DOES NOT ADDREF.
- (nsIWidget*) widget;
// convert from one event system to the other for even dispatching
- (void) convert:(NSEvent*)inEvent message:(PRInt32)inMsg toGeckoEvent:(nsInputEvent*)outGeckoEvent;
@end
//-------------------------------------------------------------------------
//
// nsChildView
//
//-------------------------------------------------------------------------
class nsChildView : public nsBaseWidget, public nsDeleteObserved, public nsIKBStateControl
{
private:
typedef nsBaseWidget Inherited;
public:
nsChildView();
virtual ~nsChildView();
NS_DECL_ISUPPORTS_INHERITED
// nsIWidget interface
NS_IMETHOD Create(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull);
NS_IMETHOD Create(nsNativeWidget aNativeParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull);
// Utility method for implementing both Create(nsIWidget ...) and
// Create(nsNativeWidget...)
virtual nsresult StandardCreate(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell,
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData,
nsNativeWidget aNativeParent = nsnull);
NS_IMETHOD Destroy();
virtual nsIWidget* GetParent(void);
NS_IMETHOD Show(PRBool aState);
NS_IMETHOD IsVisible(PRBool & aState);
NS_IMETHOD ModalEventFilter(PRBool aRealEvent, void *aEvent,
PRBool *aForWindow);
NS_IMETHOD ConstrainPosition(PRInt32 *aX, PRInt32 *aY);
NS_IMETHOD Move(PRInt32 aX, PRInt32 aY);
NS_IMETHOD Resize(PRInt32 aWidth,PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX, PRInt32 aY,PRInt32 aWidth,PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Enable(PRBool bState);
NS_IMETHOD SetFocus(PRBool aRaise);
NS_IMETHOD SetBounds(const nsRect &aRect);
NS_IMETHOD GetBounds(nsRect &aRect);
virtual nsIFontMetrics* GetFont(void);
NS_IMETHOD SetFont(const nsFont &aFont);
NS_IMETHOD Invalidate(PRBool aIsSynchronous);
NS_IMETHOD Invalidate(const nsRect &aRect,PRBool aIsSynchronous);
NS_IMETHOD InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous);
virtual void* GetNativeData(PRUint32 aDataType);
NS_IMETHOD SetColorMap(nsColorMap *aColorMap);
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect);
NS_IMETHOD WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect);
NS_IMETHOD ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect);
NS_IMETHOD BeginResizingChildren(void);
NS_IMETHOD EndResizingChildren(void);
static PRBool ConvertStatus(nsEventStatus aStatus);
NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus);
virtual PRBool DispatchMouseEvent(nsMouseEvent &aEvent);
virtual void StartDraw(nsIRenderingContext* aRenderingContext = nsnull);
virtual void EndDraw();
NS_IMETHOD Update();
virtual void UpdateWidget(nsRect& aRect, nsIRenderingContext* aContext);
virtual void ConvertToDeviceCoordinates(nscoord &aX, nscoord &aY);
void LocalToWindowCoordinate(nsPoint& aPoint) { ConvertToDeviceCoordinates(aPoint.x, aPoint.y); }
void LocalToWindowCoordinate(nscoord& aX, nscoord& aY) { ConvertToDeviceCoordinates(aX, aY); }
void LocalToWindowCoordinate(nsRect& aRect) { ConvertToDeviceCoordinates(aRect.x, aRect.y); }
NS_IMETHOD SetMenuBar(nsIMenuBar * aMenuBar);
NS_IMETHOD ShowMenuBar(PRBool aShow);
virtual nsIMenuBar* GetMenuBar();
NS_IMETHOD GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight);
NS_IMETHOD SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight);
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
NS_IMETHOD SetTitle(const nsString& title);
NS_IMETHOD GetAttention();
// Mac specific methods
void nsRectToMacRect(const nsRect& aRect, Rect& aMacRect) const;
virtual void CalcWindowRegions();
virtual PRBool PointInWidget(Point aThePoint);
virtual nsChildView* FindWidgetHit(Point aThePoint);
virtual PRBool DispatchWindowEvent(nsGUIEvent& event);
virtual PRBool DispatchWindowEvent(nsGUIEvent &event,nsEventStatus &aStatus);
virtual void AcceptFocusOnClick(PRBool aBool) { mAcceptFocusOnClick = aBool;};
PRBool AcceptFocusOnClick() { return mAcceptFocusOnClick;};
void Flash(nsPaintEvent &aEvent);
public:
// nsIKBStateControl interface
NS_IMETHOD ResetInputState();
protected:
PRBool ReportDestroyEvent();
PRBool ReportMoveEvent();
PRBool ReportSizeEvent();
NS_IMETHOD CalcOffset(PRInt32 &aX,PRInt32 &aY);
virtual PRBool OnPaint(nsPaintEvent & aEvent);
// our own impl of ::ScrollRect() that uses CopyBits so that it looks good. On
// Carbon, this just calls ::ScrollWindowRect()
void ScrollBits ( Rect & foo, PRInt32 inLeftDelta, PRInt32 inTopDelta ) ;
protected:
#if DEBUG
const char* gInstanceClassName;
#endif
nsIWidget* mParent; // my parent. could be a childview or a window [WEAK]
NSWindow* mWindow; // shortcut to the top window, [WEAK]
ChildView* mView; // my parallel cocoa view, [STRONG]
PRBool mDestroyCalled;
PRBool mDestructorCalled;
PRBool mVisible;
nsIFontMetrics* mFontMetrics;
PRBool mDrawing;
nsIRenderingContext* mTempRenderingContext;
PRBool mTempRenderingContextMadeHere;
nsPluginPort* mPluginPort;
PRBool mAcceptFocusOnClick;
};
#if DEBUG
#define WIDGET_SET_CLASSNAME(n) gInstanceClassName = (n)
#else
#define WIDGET_SET_CLASSNAME(n)
#endif
#endif // Window_h__

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,532 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// Mike Pinkerton
// Netscape Communications
//
// See header file for details.
//
// Remaining Work:
// * only convert data to clipboard on an app switch.
//
#include "nsCOMPtr.h"
#include "nsClipboard.h"
#include "nsVoidArray.h"
#include "nsIClipboardOwner.h"
#include "nsString.h"
#include "nsIFormatConverter.h"
#include "nsMimeMapper.h"
#include "nsIComponentManager.h"
#include "nsISupportsPrimitives.h"
#include "nsXPIDLString.h"
#include "nsPrimitiveHelpers.h"
#include "nsIImageMac.h"
#include "nsMemory.h"
#include <Scrap.h>
//
// nsClipboard constructor
//
nsClipboard::nsClipboard() : nsBaseClipboard()
{
}
//
// nsClipboard destructor
//
nsClipboard::~nsClipboard()
{
}
//
// SetNativeClipboardData
//
// Take data off the transferrable and put it on the clipboard in as many formats
// as are registered.
//
// NOTE: This code could all live in ForceDataToClipboard() and this could be a NOOP.
// If speed and large data sizes are an issue, we should move that code there and only
// do it on an app switch.
//
NS_IMETHODIMP
nsClipboard :: SetNativeClipboardData ( PRInt32 aWhichClipboard )
{
if ( aWhichClipboard != kGlobalClipboard )
return NS_ERROR_FAILURE;
nsresult errCode = NS_OK;
mIgnoreEmptyNotification = PR_TRUE;
// make sure we have a good transferable
if ( !mTransferable )
return NS_ERROR_INVALID_ARG;
nsMimeMapperMac theMapper;
#if TARGET_CARBON
::ClearCurrentScrap();
#else
::ZeroScrap();
#endif
// get flavor list that includes all flavors that can be written (including ones
// obtained through conversion)
nsCOMPtr<nsISupportsArray> flavorList;
errCode = mTransferable->FlavorsTransferableCanExport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return NS_ERROR_FAILURE;
// For each flavor present (either directly in the transferable or that its
// converter knows about) put it on the clipboard. Luckily, GetTransferData()
// handles conversions for us, so we really don't need to know if a conversion
// is required or not.
PRUint32 cnt;
flavorList->Count(&cnt);
for ( PRUint32 i = 0; i < cnt; ++i ) {
nsCOMPtr<nsISupports> genericFlavor;
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString( getter_Copies(flavorStr) );
// find MacOS flavor
ResType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr);
// get data. This takes converters into account. Different things happen for
// different flavors, so do some special processing.
void* data = nsnull;
PRUint32 dataSize = 0;
if ( strcmp(flavorStr,kUnicodeMime) == 0 ) {
// we have unicode, put it on first as unicode
nsCOMPtr<nsISupports> genericDataWrapper;
errCode = mTransferable->GetTransferData ( flavorStr, getter_AddRefs(genericDataWrapper), &dataSize );
nsPrimitiveHelpers::CreateDataFromPrimitive ( flavorStr, genericDataWrapper, &data, dataSize );
errCode = PutOnClipboard ( macOSFlavor, data, dataSize );
if ( NS_SUCCEEDED(errCode) ) {
// we also need to put it on as 'TEXT' after doing the conversion to the platform charset.
char* plainTextData = nsnull;
PRUnichar* castedUnicode = NS_REINTERPRET_CAST(PRUnichar*, data);
PRInt32 plainTextLen = 0;
nsPrimitiveHelpers::ConvertUnicodeToPlatformPlainText ( castedUnicode, dataSize / 2, &plainTextData, &plainTextLen );
if ( plainTextData ) {
errCode = PutOnClipboard ( 'TEXT', plainTextData, plainTextLen );
nsMemory::Free ( plainTextData );
}
}
} // if unicode
else if ( strcmp(flavorStr, kPNGImageMime) == 0 || strcmp(flavorStr, kJPEGImageMime) == 0 ||
strcmp(flavorStr, kGIFImageMime) == 0 ) {
// we have an image, which is in the transferable as an nsIImage. Convert it
// to PICT (PicHandle) and put those bits on the clipboard. The actual size
// of the picture is the size of the handle, not sizeof(Picture).
nsCOMPtr<nsISupports> imageSupports;
errCode = mTransferable->GetTransferData ( flavorStr, getter_AddRefs(imageSupports), &dataSize );
nsCOMPtr<nsIImageMac> image ( do_QueryInterface(imageSupports) );
if ( image ) {
PicHandle picture = nsnull;
image->ConvertToPICT ( &picture );
if ( picture ) {
errCode = PutOnClipboard ( 'PICT', *picture, ::GetHandleSize((Handle)picture) );
::KillPicture ( picture );
}
}
else
NS_WARNING ( "Image isn't an nsIImageMac in transferable" );
}
else {
// we don't know what we have. let's just assume it's unicode but doesn't need to be
// translated to TEXT.
nsCOMPtr<nsISupports> genericDataWrapper;
errCode = mTransferable->GetTransferData ( flavorStr, getter_AddRefs(genericDataWrapper), &dataSize );
nsPrimitiveHelpers::CreateDataFromPrimitive ( flavorStr, genericDataWrapper, &data, dataSize );
errCode = PutOnClipboard ( macOSFlavor, data, dataSize );
}
nsMemory::Free ( data );
}
} // foreach flavor in transferable
// write out the mapping data in a special flavor on the clipboard. |mappingLen|
// includes the NULL terminator.
short mappingLen = 0;
const char* mapping = theMapper.ExportMapping(&mappingLen);
if ( mapping && mappingLen ) {
errCode = PutOnClipboard ( nsMimeMapperMac::MappingFlavor(), mapping, mappingLen );
nsCRT::free ( NS_CONST_CAST(char*, mapping) );
}
return errCode;
} // SetNativeClipboardData
//
// PutOnClipboard
//
// Actually does the work of placing the data on the native clipboard
// in the given flavor
//
nsresult
nsClipboard :: PutOnClipboard ( ResType inFlavor, const void* inData, PRInt32 inLen )
{
nsresult errCode = NS_OK;
#if TARGET_CARBON
ScrapRef scrap;
::GetCurrentScrap(&scrap);
::PutScrapFlavor( scrap, inFlavor, kScrapFlavorMaskNone, inLen, inData );
#else
long numBytes = ::PutScrap ( inLen, inFlavor, inData );
if ( numBytes != noErr )
errCode = NS_ERROR_FAILURE;
#endif
return errCode;
} // PutOnClipboard
//
// GetNativeClipboardData
//
// Take data off the native clip and put it on the transferable.
//
NS_IMETHODIMP
nsClipboard :: GetNativeClipboardData ( nsITransferable * aTransferable, PRInt32 aWhichClipboard )
{
if ( aWhichClipboard != kGlobalClipboard )
return NS_ERROR_FAILURE;
nsresult errCode = NS_OK;
// make sure we have a good transferable
if ( !aTransferable )
return NS_ERROR_INVALID_ARG;
// get flavor list that includes all acceptable flavors (including ones obtained through
// conversion)
nsCOMPtr<nsISupportsArray> flavorList;
errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return NS_ERROR_FAILURE;
// create a mime mapper. It's ok for this to fail because the data may come from
// another app which obviously wouldn't put our mime mapping data on the clipboard.
char* mimeMapperData = nsnull;
errCode = GetDataOffClipboard ( nsMimeMapperMac::MappingFlavor(), (void**)&mimeMapperData, 0 );
nsMimeMapperMac theMapper ( mimeMapperData );
if (mimeMapperData)
nsCRT::free ( mimeMapperData );
// Now walk down the list of flavors. When we find one that is actually on the
// clipboard, copy out the data into the transferable in that format. SetTransferData()
// implicitly handles conversions.
PRBool dataFound = PR_FALSE;
PRUint32 cnt;
flavorList->Count(&cnt);
for ( PRUint32 i = 0; i < cnt; ++i ) {
nsCOMPtr<nsISupports> genericFlavor;
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
// find MacOS flavor (don't add if not present)
ResType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr, PR_FALSE);
void* clipboardData = nsnull;
PRInt32 dataSize = 0L;
nsresult loadResult = GetDataOffClipboard ( macOSFlavor, &clipboardData, &dataSize );
if ( NS_SUCCEEDED(loadResult) && clipboardData )
dataFound = PR_TRUE;
else {
// if we are looking for text/unicode and we fail to find it on the clipboard first,
// try again with text/plain. If that is present, convert it to unicode.
if ( strcmp(flavorStr, kUnicodeMime) == 0 ) {
loadResult = GetDataOffClipboard ( 'TEXT', &clipboardData, &dataSize );
if ( NS_SUCCEEDED(loadResult) && clipboardData ) {
const char* castedText = NS_REINTERPRET_CAST(char*, clipboardData);
PRUnichar* convertedText = nsnull;
PRInt32 convertedTextLen = 0;
nsPrimitiveHelpers::ConvertPlatformPlainTextToUnicode ( castedText, dataSize,
&convertedText, &convertedTextLen );
if ( convertedText ) {
// out with the old, in with the new
nsMemory::Free(clipboardData);
clipboardData = convertedText;
dataSize = convertedTextLen * 2;
dataFound = PR_TRUE;
}
} // if plain text data on clipboard
} // if looking for text/unicode
} // else we try one last ditch effort to find our data
if ( dataFound ) {
if ( strcmp(flavorStr, kPNGImageMime) == 0 || strcmp(flavorStr, kJPEGImageMime) == 0 ||
strcmp(flavorStr, kGIFImageMime) == 0 ) {
// someone asked for an image, so we have to convert from PICT to the desired
// image format
#ifdef DEBUG
printf ( "----------- IMAGE REQUESTED ----------" );
#endif
} // if image requested
else {
// Assume that we have some form of textual data. The DOM only wants LF, so convert
// from MacOS line endings to DOM line endings.
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks ( flavorStr, &clipboardData, &dataSize );
// put it into the transferable
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, clipboardData, dataSize, getter_AddRefs(genericDataWrapper) );
errCode = aTransferable->SetTransferData ( flavorStr, genericDataWrapper, dataSize );
}
nsMemory::Free ( clipboardData );
// we found one, get out of this loop!
break;
} // if flavor found on clipboard
}
} // foreach flavor
return errCode;
}
//
// GetDataOffClipboard
//
// Actually does the work of retrieving the data from the native clipboard
// with the given MacOS flavor
//
nsresult
nsClipboard :: GetDataOffClipboard ( ResType inMacFlavor, void** outData, PRInt32* outDataSize )
{
if ( !outData || !inMacFlavor )
return NS_ERROR_FAILURE;
// set up default results.
*outData = nsnull;
if ( outDataSize )
*outDataSize = 0;
// check if it is on the clipboard
long offsetUnused = 0;
#if TARGET_CARBON
ScrapRef scrap;
long dataSize;
OSStatus err;
err = ::GetCurrentScrap(&scrap);
if (err != noErr) return NS_ERROR_FAILURE;
err = ::GetScrapFlavorSize(scrap, inMacFlavor, &dataSize);
if (err != noErr) return NS_ERROR_FAILURE;
if (dataSize > 0) {
char* dataBuff = (char*) nsMemory::Alloc(dataSize);
if ( !dataBuff )
return NS_ERROR_OUT_OF_MEMORY;
// ::GetScrapFlavorData can be very expensive when a conversion
// is required (say the OS does the conversion from TEXT to utxt). Be
// sure to only call this when pasting. We no longer use it in
// CheckIfFlavorPresent() for this very reason.
err = ::GetScrapFlavorData(scrap, inMacFlavor, &dataSize, dataBuff);
NS_ASSERTION(err == noErr, "nsClipboard:: Error getting data off clipboard");
if ( err ) {
nsMemory::Free(dataBuff);
return NS_ERROR_FAILURE;
}
// put it into the transferable
if ( outDataSize )
*outDataSize = dataSize;
*outData = dataBuff;
}
#else
long clipResult = ::GetScrap(NULL, inMacFlavor, &offsetUnused);
if ( clipResult > 0 ) {
Handle dataHand = ::NewHandle(0);
if ( !dataHand )
return NS_ERROR_OUT_OF_MEMORY;
long dataSize = ::GetScrap ( dataHand, inMacFlavor, &offsetUnused );
NS_ASSERTION(dataSize > 0, "nsClipboard:: Error getting data off the clipboard, size negative");
if ( dataSize > 0 ) {
char* dataBuff = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(dataSize));
if ( !dataBuff )
return NS_ERROR_OUT_OF_MEMORY;
::HLock(dataHand);
::BlockMoveData ( *dataHand, dataBuff, dataSize );
::HUnlock(dataHand);
::DisposeHandle(dataHand);
if ( outDataSize )
*outDataSize = dataSize;
*outData = dataBuff;
}
else
return NS_ERROR_FAILURE;
}
#endif /* TARGET_CARBON */
return NS_OK;
} // GetDataOffClipboard
//
// HasDataMatchingFlavors
//
// Check the clipboard to see if we have any data that matches the given flavors. This
// does NOT actually fetch the data. The items in the flavor list are nsISupportsString's.
//
// Handle the case where we ask for unicode and it's not there, but plain text is. We
// say "yes" in that case, knowing that we will have to perform a conversion when we actually
// pull the data off the clipboard.
//
NS_IMETHODIMP
nsClipboard :: HasDataMatchingFlavors ( nsISupportsArray* aFlavorList, PRInt32 aWhichClipboard, PRBool * outResult )
{
nsresult rv = NS_OK;
*outResult = PR_FALSE; // assume there is nothing there we want.
if ( aWhichClipboard != kGlobalClipboard )
return NS_OK;
// create a mime mapper. It's ok for this to fail because the data may come from
// another app which obviously wouldn't put our mime mapping data on the clipboard.
char* mimeMapperData = nsnull;
rv = GetDataOffClipboard ( nsMimeMapperMac::MappingFlavor(), (void**)&mimeMapperData, 0 );
nsMimeMapperMac theMapper ( mimeMapperData );
nsMemory::Free ( mimeMapperData );
PRUint32 length;
aFlavorList->Count(&length);
for ( PRUint32 i = 0; i < length; ++i ) {
nsCOMPtr<nsISupports> genericFlavor;
aFlavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> flavorWrapper ( do_QueryInterface(genericFlavor) );
if ( flavorWrapper ) {
nsXPIDLCString flavor;
flavorWrapper->ToString ( getter_Copies(flavor) );
#ifdef NS_DEBUG
if ( strcmp(flavor, kTextMime) == 0 )
NS_WARNING ( "DO NOT USE THE text/plain DATA FLAVOR ANY MORE. USE text/unicode INSTEAD" );
#endif
// now that we have the flavor (whew!), run it through the mime mapper. If
// the mapper returns a null flavor, then it ain't there.
ResType macFlavor = theMapper.MapMimeTypeToMacOSType ( flavor, PR_FALSE );
if ( macFlavor ) {
if ( CheckIfFlavorPresent(macFlavor) ) {
*outResult = PR_TRUE; // we found one!
break;
}
else {
// if the client asked for unicode and it wasn't present, check if we have TEXT.
// We'll handle the actual data substitution in GetNativeClipboardData().
if ( strcmp(flavor, kUnicodeMime) == 0 ) {
if ( CheckIfFlavorPresent('TEXT') ) {
*outResult = PR_TRUE;
break;
}
}
}
}
}
} // foreach flavor
return NS_OK;
}
//
// CheckIfFlavorPresent
//
// A little utility routine for derminining if a given flavor is really there
//
PRBool
nsClipboard :: CheckIfFlavorPresent ( ResType inMacFlavor )
{
PRBool retval = PR_FALSE;
#if TARGET_CARBON
ScrapRef scrap = nsnull;
OSStatus err = ::GetCurrentScrap(&scrap);
if ( scrap ) {
// the OS clipboard may contain promises and require conversions. Instead
// of calling in those promises, we can use ::GetScrapFlavorInfoList() to
// see the list of what could be there if we asked for it. This is really
// fast. Iterate over the list, and if we find it, we're good to go.
UInt32 flavorCount = 0;
::GetScrapFlavorCount ( scrap, &flavorCount );
ScrapFlavorInfo* flavorList = new ScrapFlavorInfo[flavorCount];
if ( flavorList ) {
err = ::GetScrapFlavorInfoList ( scrap, &flavorCount, flavorList );
if ( !err && flavorList ) {
for ( int i = 0; i < flavorCount; ++i ) {
if ( flavorList[i].flavorType == inMacFlavor )
retval = PR_TRUE;
}
delete flavorList;
}
}
}
#else
long offsetUnused = 0;
long clipResult = ::GetScrap(NULL, inMacFlavor, &offsetUnused);
if ( clipResult > 0 )
retval = PR_TRUE; // we found one!
#endif
return retval;
} // CheckIfFlavorPresent

Просмотреть файл

@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// Mike Pinkerton
// Netscape Communications
//
// Native MacOS Clipboard Implementation of nsIClipboard. This contains
// the FE-specific implementations of the pure virtuals in nsBaseClipboard
//
#ifndef nsClipboard_h__
#define nsClipboard_h__
#include "nsBaseClipboard.h"
#include "Types.h"
class nsITransferable;
class nsClipboard : public nsBaseClipboard
{
public:
nsClipboard();
virtual ~nsClipboard();
// nsIClipboard
//NS_IMETHOD ForceDataToClipboard();
NS_IMETHOD HasDataMatchingFlavors(nsISupportsArray *aFlavorList, PRInt32 aWhichClipboard, PRBool *_retval);
protected:
// impelement the native clipboard behavior
NS_IMETHOD SetNativeClipboardData ( PRInt32 aWhichClipboard );
NS_IMETHOD GetNativeClipboardData ( nsITransferable * aTransferable, PRInt32 aWhichClipboard );
// helper to get the data off the clipboard. Caller responsible for deleting
// |outData| with delete[].
nsresult GetDataOffClipboard ( ResType inMacFlavor, void** outData, PRInt32* outDataSize ) ;
// helper to check if the data is really there
PRBool CheckIfFlavorPresent ( ResType inMacFlavor ) ;
// actually places data on the clipboard
nsresult PutOnClipboard ( ResType inFlavor, const void* inData, PRInt32 inLen ) ;
}; // nsClipboard
#endif // nsClipboard_h__

Просмотреть файл

@ -0,0 +1,208 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef MacWindow_h__
#define MacWindow_h__
#undef DARWIN
#import <Cocoa/Cocoa.h>
#include "nsIEventSink.h"
//#include <memory> // for auto_ptr
#include <Controls.h>
//using std::auto_ptr;
#include "nsBaseWidget.h"
//#include "nsMacEventHandler.h"
class nsCocoaWindow;
@interface WindowDelegate : NSObject
{
nsCocoaWindow* mGeckoWindow;
}
- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind;
- (void)windowDidResize:(NSNotification *)aNotification;
- (void)eventTimer:(NSTimer *)theTimer;
@end
//-------------------------------------------------------------------------
//
// nsCocoaWindow
//
//-------------------------------------------------------------------------
// Cocoa native window
class nsCocoaWindow : public nsBaseWidget, public nsIEventSink
{
private:
typedef nsBaseWidget Inherited;
public:
nsCocoaWindow();
virtual ~nsCocoaWindow();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIEVENTSINK
NS_IMETHOD Create(nsNativeWidget aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull);
NS_IMETHOD Create(nsIWidget* aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull);
// Utility method for implementing both Create(nsIWidget ...) and
// Create(nsNativeWidget...)
virtual nsresult StandardCreate(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell,
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData,
nsNativeWidget aNativeParent = nsnull);
NS_IMETHOD Show(PRBool aState);
NS_IMETHOD Enable(PRBool aState) { return NS_OK; }
NS_IMETHOD SetModal(PRBool aState) { return NS_OK; }
NS_IMETHOD IsVisible(PRBool & aState) { return NS_OK; }
NS_IMETHOD SetFocus(PRBool aState=PR_FALSE) { return NS_OK; }
NS_IMETHOD SetMenuBar(nsIMenuBar * aMenuBar) { return NS_OK; }
NS_IMETHOD ShowMenuBar(PRBool aShow) { return NS_OK; }
NS_IMETHOD WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect) { return NS_OK; }
NS_IMETHOD ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect) { return NS_OK; }
virtual void* GetNativeData(PRUint32 aDataType) ;
NS_IMETHOD ConstrainPosition(PRInt32 *aX, PRInt32 *aY);
NS_IMETHOD Move(PRInt32 aX, PRInt32 aY);
NS_IMETHOD PlaceBehind(nsIWidget *aWidget, PRBool aActivate);
NS_IMETHOD SetSizeMode(PRInt32 aMode);
void CalculateAndSetZoomedSize();
NS_IMETHOD Resize(PRInt32 aWidth,PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD GetScreenBounds(nsRect &aRect);
virtual PRBool OnPaint(nsPaintEvent &event);
void ReportSizeEvent();
NS_IMETHOD SetTitle(const nsString& aTitle);
virtual nsIFontMetrics* GetFont(void) { return nsnull; }
NS_IMETHOD SetFont(const nsFont &aFont) { return NS_OK; }
NS_IMETHOD Invalidate(const nsRect & aRect, PRBool aIsSynchronous) { return NS_OK; }
NS_IMETHOD Invalidate(PRBool aIsSynchronous) { return NS_OK; };
NS_IMETHOD Update() { return NS_OK; }
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) { return NS_OK; }
NS_IMETHOD SetColorMap(nsColorMap *aColorMap) { return NS_OK; }
NS_IMETHOD BeginResizingChildren(void) { return NS_OK; }
NS_IMETHOD EndResizingChildren(void) { return NS_OK; }
NS_IMETHOD GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight) { return NS_OK; }
NS_IMETHOD SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight) { return NS_OK; }
NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus) ;
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent) { return NS_OK; }
// be notified that a some form of drag event needs to go into Gecko
virtual PRBool DragEvent ( unsigned int aMessage, Point aMouseGlobal, UInt16 aKeyModifiers ) ;
// Helpers to prevent recursive resizing during live-resize
PRBool IsResizing ( ) const { return mIsResizing; }
void StartResizing ( ) { mIsResizing = PR_TRUE; }
void StopResizing ( ) { mIsResizing = PR_FALSE; }
void ComeToFront();
// nsIKBStateControl interface
NS_IMETHOD ResetInputState();
void MoveToGlobalPoint(PRInt32 aX, PRInt32 aY);
void IsActive(PRBool* aActive);
void SetIsActive(PRBool aActive);
protected:
#if 0
pascal static OSErr DragTrackingHandler ( DragTrackingMessage theMessage, WindowPtr theWindow,
void *handlerRefCon, DragReference theDrag );
pascal static OSErr DragReceiveHandler (WindowPtr theWindow,
void *handlerRefCon, DragReference theDragRef) ;
DragTrackingHandlerUPP mDragTrackingHandlerUPP;
DragReceiveHandlerUPP mDragReceiveHandlerUPP;
#endif
#if 0
pascal static OSStatus WindowEventHandler ( EventHandlerCallRef inHandlerChain,
EventRef inEvent, void* userData ) ;
pascal static OSStatus ScrollEventHandler ( EventHandlerCallRef inHandlerChain,
EventRef inEvent, void* userData ) ;
#endif
#if 0
PRBool mIsDialog; // true if the window is a dialog
auto_ptr<nsMacEventHandler> mMacEventHandler;
nsIWidget *mOffsetParent;
PRBool mAcceptsActivation;
PRBool mIsActive;
PRBool mZoomOnShow;
#endif // COCOA
PRBool mIsResizing; // we originated the resize, prevent infinite recursion
PRBool mWindowMadeHere; // true if we created the window, false for embedding
NSWindow* mWindow; // our cocoa window [STRONG]
NSTimer* mEventTimer; // event timer [STRONG]
WindowDelegate* mDelegate; // our delegate for processing window msgs [STRONG]
};
#endif // MacWindow_h__

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDeleteObserver.h"
#include "nsVoidArray.h"
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsDeleteObserved::nsDeleteObserved(void* aObject)
{
mDeleteObserverArray = nsnull;
mObject = (aObject ? aObject : this);
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsDeleteObserved::~nsDeleteObserved()
{
if (mDeleteObserverArray)
{
// notify observers of the delete
for (PRInt32 i = mDeleteObserverArray->Count() - 1; i >= 0; --i)
{
nsDeleteObserver* deleteObserver = static_cast<nsDeleteObserver*>(mDeleteObserverArray->ElementAt(i));
if (deleteObserver)
deleteObserver->NotifyDelete(mObject);
}
delete mDeleteObserverArray;
mDeleteObserverArray = nsnull;
}
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
PRBool nsDeleteObserved::AddDeleteObserver(nsDeleteObserver* aDeleteObserver)
{
if (! mDeleteObserverArray)
mDeleteObserverArray = new nsVoidArray();
if (mDeleteObserverArray)
return mDeleteObserverArray->AppendElement(aDeleteObserver);
return PR_FALSE;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
PRBool nsDeleteObserved::RemoveDeleteObserver(nsDeleteObserver* aDeleteObserver)
{
if (mDeleteObserverArray)
return mDeleteObserverArray->RemoveElement(aDeleteObserver);
return PR_FALSE;
}

Просмотреть файл

@ -0,0 +1,86 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef DeleteObserver_h__
#define DeleteObserver_h__
#include "prtypes.h"
class nsVoidArray;
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
//
// This is a small utility class which allows to notify an object
// (the "observer") holding a reference on another object
// (the "observed") that the observed object has been deleted.
//
// As you imagine, it's reserved to cases where XPCOM refCouting doesn't fit.
// It is used by the MacEventHandler and the Toolkit to hold references
// on the focused widget and the the last widget hit.
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
class nsDeleteObserver
{
public:
virtual void NotifyDelete(void* aDeletedObject) = 0;
};
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
class nsDeleteObserved
{
public:
nsDeleteObserved(void* aObject);
virtual ~nsDeleteObserved();
PRBool AddDeleteObserver(nsDeleteObserver* aDeleteObserver);
PRBool RemoveDeleteObserver(nsDeleteObserver* aDeleteObserver);
private:
nsVoidArray* mDeleteObserverArray;
void* mObject;
};
#endif //DeleteObserver_h__

Просмотреть файл

@ -0,0 +1,899 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// Mike Pinkerton
// Netscape Communications
//
// See associated header file for details
//
#include "nsDragService.h"
#include "nsITransferable.h"
#include "nsString.h"
#include "nsMimeMapper.h"
#include "nsClipboard.h"
#include "nsIRegion.h"
#include "nsVoidArray.h"
#include "nsISupportsPrimitives.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsPrimitiveHelpers.h"
#ifndef XP_MACOSX
#include "nsILocalFileMac.h"
#endif
#include "nsWatchTask.h"
// rjc
#include <Gestalt.h>
#include "nsIContent.h"
#include "nsIDOMNode.h"
#include "nsIDocument.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIFrame.h"
#include "nsIView.h"
#include "nsRect.h"
#include "nsPoint.h"
#include "nsIWidget.h"
#include "nsCarbonHelpers.h"
#include "nsIXULContent.h"
#include "nsIDOMElement.h"
// we need our own stuff for MacOS because of nsIDragSessionMac.
NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_QUERY_INTERFACE3(nsDragService, nsIDragService, nsIDragSession, nsIDragSessionMac)
//
// DragService constructor
//
nsDragService::nsDragService()
: mDragRef(0), mDataItems(nsnull), mImageDraggingSupported(PR_FALSE), mDragSendDataUPP(nsnull)
{
#if USE_TRANSLUCENT_DRAGS
// check if the Drag Manager supports image dragging
// however, it doesn't really work too well, so let's back off (pinkerton)
long response;
OSErr err = Gestalt(gestaltDragMgrAttr, &response);
if (err == noErr && (response & (1L << gestaltDragMgrHasImageSupport))) {
mImageDraggingSupported = PR_TRUE;
}
#endif
mDragSendDataUPP = NewDragSendDataUPP(DragSendDataProc);
}
//
// DragService destructor
//
nsDragService::~nsDragService()
{
if ( mDragSendDataUPP )
::DisposeDragSendDataUPP(mDragSendDataUPP);
}
PRBool
nsDragService :: ComputeGlobalRectFromFrame ( nsIDOMNode* aDOMNode, Rect & outScreenRect )
{
NS_ASSERTION ( aDOMNode, "Oopps, no DOM node" );
// this isn't so much of an issue as long as we're just dragging around outlines,
// but it is when we are showing the text being drawn. Comment it out for now
// but leave it around when we turn this all back on (pinkerton).
#if USE_TRANSLUCENT_DRAGGING
// until bug 41237 is fixed, only do translucent dragging if the drag is in
// the chrome or it's a link.
nsCOMPtr<nsIXULContent> xulContent ( do_QueryInterface(aDOMNode) );
if ( !xulContent ) {
// the link node is the parent of the node we have (which is probably text or image).
nsCOMPtr<nsIDOMNode> parent;
aDOMNode->GetParentNode ( getter_AddRefs(parent) );
if ( parent ) {
nsAutoString localName;
parent->GetLocalName ( localName );
if ( ! localName.Equals(NS_LITERAL_STRING("A")) )
return PR_FALSE;
}
else
return FALSE;
}
#endif
PRBool haveRectFlag = PR_FALSE;
outScreenRect.left = outScreenRect.right = outScreenRect.top = outScreenRect.bottom = 0;
// Get the frame for this content node (note: frames are not refcounted)
nsIFrame *aFrame = nsnull;
nsCOMPtr<nsIPresContext> presContext;
GetFrameFromNode ( aDOMNode, &aFrame, getter_AddRefs(presContext) );
if ( !aFrame || !presContext )
return PR_FALSE;
//
// Now that we have the frame, we have to convert its coordinates into global screen
// coordinates.
//
nsRect aRect(0,0,0,0);
nsIView *parentView = nsnull;
aFrame->GetRect(aRect);
// Find offset from our view
nsIView *containingView = nsnull;
nsPoint viewOffset(0,0);
aFrame->GetOffsetFromView(presContext, viewOffset, &containingView);
NS_ASSERTION(containingView, "No containing view!");
if ( !containingView )
return PR_FALSE;
// get the widget associated with the containing view.
nsCOMPtr<nsIWidget> aWidget;
nscoord widgetOffsetX = 0, widgetOffsetY = 0;
containingView->GetOffsetFromWidget ( &widgetOffsetX, &widgetOffsetY, *getter_AddRefs(aWidget) );
if (aWidget) {
float t2p = 1.0;
presContext->GetTwipsToPixels(&t2p);
// GetOffsetFromWidget() actually returns the _parent's_ offset from its widget, so we
// still have to add in the offset to |containingView|'s parent ourselves.
nscoord viewOffsetToParentX = 0, viewOffsetToParentY = 0;
containingView->GetPosition ( &viewOffsetToParentX, &viewOffsetToParentY );
// Shift our offset rect by offset into our view, the view's offset to its parent, and
// the parent's offset to the closest widget. Then convert that to global coordinates.
// Recall that WidgetToScreen() will give us the global coordinates of the rectangle we
// give it, but it expects everything to be in pixels.
nsRect screenOffset;
screenOffset.MoveBy ( NSTwipsToIntPixels(widgetOffsetX + viewOffsetToParentX + viewOffset.x, t2p),
NSTwipsToIntPixels(widgetOffsetY + viewOffsetToParentY + viewOffset.y, t2p) );
aWidget->WidgetToScreen ( screenOffset, screenOffset );
// stash it all in a mac rect
outScreenRect.left = screenOffset.x;
outScreenRect.top = screenOffset.y;
outScreenRect.right = outScreenRect.left + NSTwipsToIntPixels(aRect.width, t2p);
outScreenRect.bottom = outScreenRect.top + NSTwipsToIntPixels(aRect.height, t2p);
haveRectFlag = PR_TRUE;
}
return haveRectFlag;
} // ComputeGlobalRectFromFrame
//
// StartDragSession
//
// Do all the work to kick it off.
//
NS_IMETHODIMP
nsDragService :: InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * aTransferableArray, nsIScriptableRegion * aDragRgn, PRUint32 aActionType)
{
::InitCursor();
nsBaseDragService::InvokeDragSession ( aDOMNode, aTransferableArray, aDragRgn, aActionType );
DragReference theDragRef;
OSErr result = ::NewDrag(&theDragRef);
if ( result != noErr )
return NS_ERROR_FAILURE;
mDragRef = theDragRef;
#if DEBUG_DD
printf("**** created drag ref %ld\n", theDragRef);
#endif
// add the flavors from the transferables. Cache this array for the send data proc
mDataItems = aTransferableArray;
RegisterDragItemsAndFlavors ( aTransferableArray ) ;
Rect frameRect = { 0, 0, 0, 0 };
RgnHandle theDragRgn = ::NewRgn();
::RectRgn(theDragRgn, &frameRect);
if ( mImageDraggingSupported ) {
Point imgOffsetPt;
imgOffsetPt.v = imgOffsetPt.h = 0;
PRBool canUseRect = BuildDragRegion ( aDragRgn, aDOMNode, theDragRgn );
if ( canUseRect ) {
// passing in null for image's PixMapHandle to SetDragImage() means use bits on screen
::SetDragImage (theDragRef, nsnull, theDragRgn, imgOffsetPt, kDragDarkerTranslucency);
}
}
else
BuildDragRegion ( aDragRgn, aDOMNode, theDragRgn );
// we have to synthesize the native event because we may be called from JavaScript
// through XPConnect. In that case, we only have a DOM event and no way to
// get to the native event. As a consequence, we just always fake it.
EventRecord theEvent;
theEvent.what = mouseDown;
theEvent.message = 0L;
theEvent.when = 0L;
theEvent.modifiers = 0L;
// since we don't have the original mouseDown location, just assume the drag
// started in the middle of the frame. This prevents us from having the mouse
// and the region we're dragging separated by a big gap (which could happen if
// we used the current mouse position). I know this isn't exactly right, and you can
// see it if you're paying attention, but who pays such close attention?
Rect dragRect;
::GetRegionBounds(theDragRgn, &dragRect);
theEvent.where.v = rint(dragRect.top + (dragRect.bottom - dragRect.top) / 2);
theEvent.where.h = rint(dragRect.left + (dragRect.right - dragRect.left) / 2);
// register drag send proc which will call us back when asked for the actual
// flavor data (instead of placing it all into the drag manager)
::SetDragSendProc ( theDragRef, mDragSendDataUPP, this );
// start the drag. Be careful, mDragRef will be invalid AFTER this call (it is
// reset by the dragTrackingHandler).
StartDragSession();
::TrackDrag ( theDragRef, &theEvent, theDragRgn );
EndDragSession();
// clean up after ourselves
::DisposeRgn ( theDragRgn );
result = ::DisposeDrag ( theDragRef );
#if DEBUG_DD
printf("**** disposing drag ref %ld\n", theDragRef);
#endif
NS_ASSERTION ( result == noErr, "Error disposing drag" );
mDragRef = 0L;
mDataItems = nsnull;
return NS_OK;
} // StartDragSession
//
// BuildDragRegion
//
// Given the XP region describing the drag rectangles, build up an appropriate drag region. If
// the region we're given is null, try the given DOM node. If that doesn't work fake it as
// best we can.
//
// Returns PR_TRUE if the region is something that can be used with SetDragImage()
//
PRBool
nsDragService :: BuildDragRegion ( nsIScriptableRegion* inRegion, nsIDOMNode* inNode, RgnHandle ioDragRgn )
{
PRBool retVal = PR_TRUE;
nsCOMPtr<nsIRegion> geckoRegion;
if ( inRegion )
inRegion->GetRegion(getter_AddRefs(geckoRegion));
// create the drag region. Pull out the native mac region from the nsIRegion we're
// given, copy it, inset it one pixel, and subtract them so we're left with just an
// outline. Too bad we can't do this with gfx api's.
//
// At the end, we are left with an outline of the region in global coordinates.
if ( geckoRegion ) {
RgnHandle dragRegion = nsnull;
geckoRegion->GetNativeRegion((void*&)dragRegion);
if ( dragRegion && ioDragRgn ) {
::CopyRgn ( dragRegion, ioDragRgn );
::InsetRgn ( ioDragRgn, 1, 1 );
::DiffRgn ( dragRegion, ioDragRgn, ioDragRgn );
// now shift the region into global coordinates.
Point offsetFromLocalToGlobal = { 0, 0 };
::LocalToGlobal ( &offsetFromLocalToGlobal );
::OffsetRgn ( ioDragRgn, offsetFromLocalToGlobal.h, offsetFromLocalToGlobal.v );
}
}
else {
PRBool useRectFromFrame = PR_FALSE;
// no region provided, let's try to use the dom node to get the frame. Pick a
// silly default in case we can't get it.
Point currMouse;
::GetMouse(&currMouse);
Rect frameRect = { currMouse.v, currMouse.h, currMouse.v + 25, currMouse.h + 100 };
if ( inNode )
useRectFromFrame = ComputeGlobalRectFromFrame ( inNode, frameRect );
else
NS_WARNING ( "Can't find anything to get a drag rect from. I'm dyin' out here!" );
if ( ioDragRgn ) {
RgnHandle frameRgn = ::NewRgn();
if ( frameRgn ) {
::RectRgn ( frameRgn, &frameRect );
::CopyRgn ( frameRgn, ioDragRgn );
::InsetRgn ( ioDragRgn, 1, 1 );
::DiffRgn ( frameRgn, ioDragRgn, ioDragRgn );
::DisposeRgn ( frameRgn );
}
}
// if we couldn't find the exact frame coordinates, then we need to alert people that
// they shouldn't use this as the basis of SetDragImage()
retVal = useRectFromFrame;
}
return retVal;
} // BuildDragRegion
//
// RegisterDragItemsAndFlavors
//
// Takes the multiple drag items from an array of transferables and registers them
// and their flavors with the MacOS DragManager. Note that we don't actually place
// any of the data there yet, but will rely on a sendDataProc to get the data as
// requested.
//
void
nsDragService :: RegisterDragItemsAndFlavors ( nsISupportsArray * inArray )
{
const FlavorFlags flags = 0;
unsigned int numDragItems = 0;
inArray->Count ( &numDragItems ) ;
for ( int itemIndex = 0; itemIndex < numDragItems; ++itemIndex ) {
nsMimeMapperMac theMapper;
nsCOMPtr<nsISupports> genericItem;
inArray->GetElementAt ( itemIndex, getter_AddRefs(genericItem) );
nsCOMPtr<nsITransferable> currItem ( do_QueryInterface(genericItem) );
if ( currItem ) {
nsCOMPtr<nsISupportsArray> flavorList;
if ( NS_SUCCEEDED(currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList))) ) {
PRUint32 numFlavors;
flavorList->Count ( &numFlavors );
for ( int flavorIndex = 0; flavorIndex < numFlavors; ++flavorIndex ) {
nsCOMPtr<nsISupports> genericWrapper;
flavorList->GetElementAt ( flavorIndex, getter_AddRefs(genericWrapper) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericWrapper) );
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
FlavorType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr);
::AddDragItemFlavor ( mDragRef, itemIndex, macOSFlavor, NULL, 0, flags );
// If we advertise text/unicode, then make sure we add 'TEXT' to the list
// of flavors supported since we will do the conversion ourselves in GetDataForFlavor()
if ( strcmp(flavorStr, kUnicodeMime) == 0 ) {
theMapper.MapMimeTypeToMacOSType(kTextMime);
::AddDragItemFlavor ( mDragRef, itemIndex, 'TEXT', NULL, 0, flags );
}
}
} // foreach flavor in item
} // if valid flavor list
} // if item is a transferable
// put the mime mapping data for this item in a special flavor. Unlike the other data,
// we have to put the data in now (rather than defer it) or the mappings will go out
// of scope by the time they are asked for. Remember that the |mappingLen|
// includes the null, and we need to maintain that for when we parse it.
short mappingLen;
char* mapping = theMapper.ExportMapping(&mappingLen);
if ( mapping && mappingLen ) {
::AddDragItemFlavor ( mDragRef, itemIndex, nsMimeMapperMac::MappingFlavor(),
mapping, mappingLen, flags );
nsCRT::free ( mapping );
}
} // foreach drag item
} // RegisterDragItemsAndFlavors
//
// GetData
//
// Pull data out of the OS drag item at the requested index and stash it into the
// given transferable. Only put in the data with the highest fidelity asked for and
// stop as soon as we find a match.
//
NS_IMETHODIMP
nsDragService :: GetData ( nsITransferable * aTransferable, PRUint32 aItemIndex )
{
nsresult errCode = NS_ERROR_FAILURE;
// make sure we have a good transferable
if ( !aTransferable )
return NS_ERROR_INVALID_ARG;
// get flavor list that includes all acceptable flavors (including ones obtained through
// conversion). Flavors are nsISupportsStrings so that they can be seen from JS.
nsCOMPtr<nsISupportsArray> flavorList;
errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return errCode;
// get the data for the requested drag item. Remember that GetDragItemReferenceNumber()
// is one-based NOT zero-based like |aItemIndex| is.
ItemReference itemRef;
::GetDragItemReferenceNumber ( mDragRef, aItemIndex + 1, &itemRef );
// create a mime mapper to help us out based on data in a special flavor for this item
char* mappings = LookupMimeMappingsForItem(mDragRef, itemRef);
nsMimeMapperMac theMapper ( mappings );
nsCRT::free ( mappings );
// Now walk down the list of flavors. When we find one that is actually present,
// copy out the data into the transferable in that format. SetTransferData()
// implicitly handles conversions.
PRUint32 cnt;
flavorList->Count ( &cnt );
for ( int i = 0; i < cnt; ++i ) {
nsCOMPtr<nsISupports> genericWrapper;
flavorList->GetElementAt ( i, getter_AddRefs(genericWrapper) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericWrapper) );
if ( currentFlavor ) {
// find MacOS flavor (but don't add it if it's not there)
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
FlavorType macOSFlavor = theMapper.MapMimeTypeToMacOSType(flavorStr, PR_FALSE);
#if DEBUG_DD
printf("looking for data in type %s, mac flavor %ld\n", NS_STATIC_CAST(const char*,flavorStr), macOSFlavor);
#endif
// check if it is present in the current drag item.
FlavorFlags unused;
PRBool dataFound = PR_FALSE;
void* dataBuff;
PRInt32 dataSize = 0;
if ( macOSFlavor && ::GetFlavorFlags(mDragRef, itemRef, macOSFlavor, &unused) == noErr ) {
nsresult loadResult = ExtractDataFromOS(mDragRef, itemRef, macOSFlavor, &dataBuff, &dataSize);
if ( NS_SUCCEEDED(loadResult) && dataBuff )
dataFound = PR_TRUE;
}
else {
// if we are looking for text/unicode and we fail to find it on the clipboard first,
// try again with text/plain. If that is present, convert it to unicode.
if ( strcmp(flavorStr, kUnicodeMime) == 0 ) {
if ( ::GetFlavorFlags(mDragRef, itemRef, 'TEXT', &unused) == noErr ) {
nsresult loadResult = ExtractDataFromOS(mDragRef, itemRef, 'TEXT', &dataBuff, &dataSize);
if ( NS_SUCCEEDED(loadResult) && dataBuff ) {
const char* castedText = NS_REINTERPRET_CAST(char*, dataBuff);
PRUnichar* convertedText = nsnull;
PRInt32 convertedTextLen = 0;
nsPrimitiveHelpers::ConvertPlatformPlainTextToUnicode ( castedText, dataSize,
&convertedText, &convertedTextLen );
if ( convertedText ) {
// out with the old, in with the new
nsMemory::Free(dataBuff);
dataBuff = convertedText;
dataSize = convertedTextLen * 2;
dataFound = PR_TRUE;
}
} // if plain text data on clipboard
} // if plain text flavor present
} // if looking for text/unicode
} // else we try one last ditch effort to find our data
if ( dataFound ) {
nsCOMPtr<nsISupports> genericDataWrapper;
if ( strcmp(flavorStr, kFileMime) == 0 ) {
// we have a HFSFlavor struct in |dataBuff|. Create an nsLocalFileMac object.
HFSFlavor* fileData = NS_REINTERPRET_CAST(HFSFlavor*, dataBuff);
NS_ASSERTION ( sizeof(HFSFlavor) == dataSize, "Ooops, we realy don't have a HFSFlavor" );
#ifndef XP_MACOSX
nsCOMPtr<nsILocalFileMac> file;
if ( NS_SUCCEEDED(NS_NewLocalFileWithFSSpec(&fileData->fileSpec, PR_TRUE, getter_AddRefs(file))) )
genericDataWrapper = do_QueryInterface(file);
#endif
}
else {
// we probably have some form of text. The DOM only wants LF, so convert k
// from MacOS line endings to DOM line endings.
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks ( flavorStr, &dataBuff, NS_REINTERPRET_CAST(int*, &dataSize) );
nsPrimitiveHelpers::CreatePrimitiveForData ( flavorStr, dataBuff, dataSize, getter_AddRefs(genericDataWrapper) );
}
// put it into the transferable.
errCode = aTransferable->SetTransferData ( flavorStr, genericDataWrapper, dataSize );
#ifdef NS_DEBUG
if ( errCode != NS_OK ) printf("nsDragService:: Error setting data into transferable\n");
#endif
nsMemory::Free ( dataBuff );
errCode = NS_OK;
// we found one, get out of this loop!
break;
}
}
} // foreach flavor
return errCode;
}
//
// IsDataFlavorSupported
//
// Check the OS to see if the given drag flavor is in the list. Oddly returns
// NS_OK for success and NS_ERROR_FAILURE if flavor is not present.
//
// Handle the case where we ask for unicode and it's not there, but plain text is. We
// say "yes" in that case, knowing that we will have to perform a conversion when we actually
// pull the data out of the drag.
//
// ¥¥¥ this is obviously useless with more than one drag item. Need to specify
// ¥¥¥Êand index to this API
//
NS_IMETHODIMP
nsDragService :: IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
{
if ( !_retval )
return NS_ERROR_INVALID_ARG;
#ifdef NS_DEBUG
if ( strcmp(aDataFlavor, kTextMime) == 0 )
NS_WARNING ( "DO NOT USE THE text/plain DATA FLAVOR ANY MORE. USE text/unicode INSTEAD" );
#endif
*_retval = PR_FALSE;
// search through all drag items looking for something with this flavor. Recall
// that drag item indices are 1-based.
unsigned short numDragItems = 0;
::CountDragItems ( mDragRef, &numDragItems );
for ( int i = 1; i <= numDragItems; ++i ) {
ItemReference currItem;
OSErr res = ::GetDragItemReferenceNumber ( mDragRef, i, &currItem );
if ( res != noErr )
return NS_ERROR_FAILURE;
// convert to 4 character MacOS type for this item
char* mappings = LookupMimeMappingsForItem(mDragRef, currItem) ;
nsMimeMapperMac theMapper ( mappings );
FlavorType macFlavor = theMapper.MapMimeTypeToMacOSType(aDataFlavor, PR_FALSE);
nsMemory::Free(mappings);
FlavorFlags ignored;
if ( ::GetFlavorFlags(mDragRef, currItem, macFlavor, &ignored) == noErr )
*_retval = PR_TRUE;
else {
// if the client asked for unicode and it wasn't present, check if we have TEXT.
// We'll handle the actual data substitution in GetDataForFlavor().
if ( strcmp(aDataFlavor, kUnicodeMime) == 0 ) {
if ( ::GetFlavorFlags(mDragRef, currItem, 'TEXT', &ignored) == noErr )
*_retval = PR_TRUE;
}
}
} // for each item in drag
return NS_OK;
} // IsDataFlavorSupported
//
// GetNumDropItems
//
// Returns the number of drop items present in the current drag.
//
NS_IMETHODIMP
nsDragService :: GetNumDropItems ( PRUint32 * aNumItems )
{
// we have to put it into a short first because that's what the MacOS API's expect.
// After it's in a short, getting it into a long is no problem. Oh well.
unsigned short numDragItems = 0;
OSErr result = ::CountDragItems ( mDragRef, &numDragItems );
*aNumItems = numDragItems;
return ( result == noErr ? NS_OK : NS_ERROR_FAILURE );
} // GetNumDropItems
//
// SetDragReference
//
// An API to allow the drag manager callback functions to tell the session about the
// current dragRef w/out resorting to knowing the internals of the implementation
//
NS_IMETHODIMP
nsDragService :: SetDragReference ( DragReference aDragRef )
{
mDragRef = aDragRef;
return NS_OK;
} // SetDragReference
//
// DragSendDataProc
//
// Called when a drop occurs and the drop site asks for the data.
//
// This will only get called when Mozilla is the originator of the drag, so we can
// make certain assumptions. One is that we've cached the list of transferables in the
// drag session. The other is that the item ref is the index into this list so we
// can easily pull out the item asked for.
//
// We cannot rely on |mDragRef| at this point so we have to use what was passed in
// and pass that along.
//
pascal OSErr
nsDragService :: DragSendDataProc ( FlavorType inFlavor, void* inRefCon, ItemReference inItemRef,
DragReference inDragRef )
{
OSErr retVal = noErr;
nsDragService* self = NS_STATIC_CAST(nsDragService*, inRefCon);
NS_ASSERTION ( self, "Refcon not set correctly for DragSendDataProc" );
if ( self ) {
void* data = nsnull;
PRUint32 dataSize = 0;
retVal = self->GetDataForFlavor ( self->mDataItems, inDragRef, inItemRef, inFlavor, &data, &dataSize );
if ( retVal == noErr ) {
// make the data accessable to the DragManager
retVal = ::SetDragItemFlavorData ( inDragRef, inItemRef, inFlavor, data, dataSize, 0 );
NS_ASSERTION ( retVal == noErr, "SDIFD failed in DragSendDataProc" );
}
nsMemory::Free ( data );
} // if valid refcon
return retVal;
} // DragSendDataProc
//
// GetDataForFlavor
//
// Given a MacOS flavor and an index for which drag item to lookup, get the information from the
// drag item corresponding to this flavor.
//
// This routine also handles the conversions between text/plain and text/unicode to take platform
// charset encodings into account. If someone asks for text/plain, we convert the unicode (we assume
// it is present because that's how we knew to advertise text/plain in the first place) and give it
// to them. If someone asks for text/unicode, and it isn't there, we need to convert text/plain and
// hand them back the unicode. Again, we can assume that text/plain is there because otherwise we
// wouldn't have been allowed to look for unicode.
//
OSErr
nsDragService :: GetDataForFlavor ( nsISupportsArray* inDragItems, DragReference inDragRef, unsigned int inItemIndex,
FlavorType inFlavor, void** outData, unsigned int* outDataSize )
{
if ( !inDragItems || !inDragRef )
return paramErr;
OSErr retVal = noErr;
// (assumes that the items were placed into the transferable as nsITranferable*'s, not nsISupports*'s.)
nsCOMPtr<nsISupports> genericItem;
inDragItems->GetElementAt ( inItemIndex, getter_AddRefs(genericItem) );
nsCOMPtr<nsITransferable> item ( do_QueryInterface(genericItem) );
if ( item ) {
nsCAutoString mimeFlavor;
// create a mime mapper to help us out based on data in a special flavor for this item.
char* mappings = LookupMimeMappingsForItem(inDragRef, inItemIndex) ;
nsMimeMapperMac theMapper ( mappings );
theMapper.MapMacOSTypeToMimeType ( inFlavor, mimeFlavor );
nsMemory::Free ( mappings );
// if someone was asking for text/plain, lookup unicode instead so we can convert it.
PRBool needToDoConversionToPlainText = PR_FALSE;
const char* actualFlavor = mimeFlavor;
if ( strcmp(mimeFlavor,kTextMime) == 0 ) {
actualFlavor = kUnicodeMime;
needToDoConversionToPlainText = PR_TRUE;
}
else
actualFlavor = mimeFlavor;
*outDataSize = 0;
nsCOMPtr<nsISupports> data;
if ( NS_SUCCEEDED(item->GetTransferData(actualFlavor, getter_AddRefs(data), outDataSize)) ) {
nsPrimitiveHelpers::CreateDataFromPrimitive ( actualFlavor, data, outData, *outDataSize );
// if required, do the extra work to convert unicode to plain text and replace the output
// values with the plain text.
if ( needToDoConversionToPlainText ) {
char* plainTextData = nsnull;
PRUnichar* castedUnicode = NS_REINTERPRET_CAST(PRUnichar*, *outData);
PRInt32 plainTextLen = 0;
nsPrimitiveHelpers::ConvertUnicodeToPlatformPlainText ( castedUnicode, *outDataSize / 2, &plainTextData, &plainTextLen );
if ( *outData ) {
nsMemory::Free(*outData);
*outData = plainTextData;
*outDataSize = plainTextLen;
}
else
retVal = cantGetFlavorErr;
}
}
else
retVal = cantGetFlavorErr;
} // if valid item
return retVal;
} // GetDataForFlavor
//
// LookupMimeMappingsForItem
//
// load up the flavor data for the mime mapper from the drag item and create a
// mime mapper to help us go between mime types and macOS flavors. It may not be
// there (such as when the drag originated from another app), but that's ok.
//
// Caller is responsible for deleting the memory.
//
char*
nsDragService :: LookupMimeMappingsForItem ( DragReference inDragRef, ItemReference inItemRef )
{
char* mapperData = nsnull;
PRInt32 mapperSize = 0;
ExtractDataFromOS(inDragRef, inItemRef, nsMimeMapperMac::MappingFlavor(), (void**)&mapperData, &mapperSize);
return mapperData;
#if 0
OSErr err = ::GetFlavorDataSize ( inDragRef, itemRef, nsMimeMapperMac::MappingFlavor(), &mapperSize );
if ( !err && mapperSize > 0 ) {
mapperData = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(mapperSize + 1));
if ( !mapperData )
return nsnull;
err = ::GetFlavorData ( inDragRef, itemRef, nsMimeMapperMac::MappingFlavor(), mapperData, &mapperSize, 0 );
if ( err ) {
#ifdef NS_DEBUG
printf("nsDragService: Error getting data out of drag manager for mime mapper, #%ld\n", err);
#endif
return nsnull;
}
else
mapperData[mapperSize] = '\0'; // null terminate the data
}
return mapperData;
#endif
}
//
// ExtractDataFromOS
//
// Handles pulling the data from the DragManager. Will return NS_ERROR_FAILURE if it can't get
// the data for whatever reason.
//
nsresult
nsDragService :: ExtractDataFromOS ( DragReference inDragRef, ItemReference inItemRef, ResType inFlavor,
void** outBuffer, PRInt32* outBuffSize )
{
if ( !outBuffer || !outBuffSize || !inFlavor )
return NS_ERROR_FAILURE;
nsresult retval = NS_OK;
char* buff = nsnull;
Size buffSize = 0;
OSErr err = ::GetFlavorDataSize ( inDragRef, inItemRef, inFlavor, &buffSize );
if ( !err && buffSize > 0 ) {
buff = NS_REINTERPRET_CAST(char*, nsMemory::Alloc(buffSize + 1));
if ( buff ) {
err = ::GetFlavorData ( inDragRef, inItemRef, inFlavor, buff, &buffSize, 0 );
if ( err ) {
#ifdef NS_DEBUG
printf("nsDragService: Error getting data out of drag manager, #%ld\n", err);
#endif
retval = NS_ERROR_FAILURE;
}
}
else
retval = NS_ERROR_FAILURE;
}
if ( NS_FAILED(retval) ) {
if ( buff )
nsMemory::Free(buff);
}
else {
*outBuffer = buff;
*outBuffSize = buffSize;
}
return retval;
} // ExtractDataFromOS
//
// StartDragSession
// EndDragSession
//
// Override the defaults to disable/enable the watch cursor while we're dragging
//
nsresult
nsDragService :: StartDragSession ( )
{
nsWatchTask::GetTask().Suspend();
return nsBaseDragService::StartDragSession();
}
nsresult
nsDragService :: EndDragSession ( )
{
nsWatchTask::GetTask().Resume();
return nsBaseDragService::EndDragSession();
}
//
// SetDragAction
//
// Override to set the cursor to the appropriate feedback when the
// drag action changes based on modifier keys
//
NS_IMETHODIMP
nsDragService :: SetDragAction ( PRUint32 anAction )
{
const PRInt32 kCopyCursorID = 144;
const PRInt32 kLinkCursorID = 145;
// don't do the work if it's the same.
if ( anAction == mDragAction )
return NS_OK;
CursHandle newCursor = nsnull;
if ( anAction == DRAGDROP_ACTION_COPY )
newCursor = ::GetCursor ( kCopyCursorID );
else if ( anAction == DRAGDROP_ACTION_LINK )
newCursor = ::GetCursor ( kLinkCursorID );
if ( newCursor ) {
::HLock((Handle)newCursor);
::SetCursor ( *newCursor );
::HUnlock((Handle)newCursor);
}
else
::InitCursor();
return nsBaseDragService::SetDragAction(anAction);
}

Просмотреть файл

@ -0,0 +1,113 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// Mike Pinkerton
// Netscape Communications
//
// The MacOS native implementation of nsIDragService, nsIDragSession, and
// nsIDragSessionMac.
//
#ifndef nsDragService_h__
#define nsDragService_h__
#include "nsBaseDragService.h"
#include "nsIDragSessionMac.h"
#include <Drag.h>
#include <MacWindows.h>
class nsNativeDragTarget;
class nsDragService : public nsBaseDragService, public nsIDragSessionMac
{
public:
nsDragService();
virtual ~nsDragService();
//nsISupports - can't use inherited because of nsIDragSessionMac
NS_DECL_ISUPPORTS_INHERITED
//nsIDragService
NS_IMETHOD InvokeDragSession (nsIDOMNode *aDOMNode, nsISupportsArray * anArrayTransferables, nsIScriptableRegion * aRegion, PRUint32 aActionType);
//nsIDragSession
NS_IMETHOD GetData (nsITransferable * aTransferable, PRUint32 aItemIndex);
NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval);
NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems);
NS_IMETHOD SetDragAction ( PRUint32 anAction ) ;
//nsIDragSessionMac
NS_IMETHOD SetDragReference ( DragReference aDragRef ) ;
private:
NS_IMETHOD StartDragSession ( ) ;
NS_IMETHOD EndDragSession ( ) ;
char* LookupMimeMappingsForItem ( DragReference inDragRef, ItemReference itemRef ) ;
void RegisterDragItemsAndFlavors ( nsISupportsArray * inArray ) ;
PRBool BuildDragRegion ( nsIScriptableRegion* inRegion, nsIDOMNode* inNode, RgnHandle ioDragRgn ) ;
OSErr GetDataForFlavor ( nsISupportsArray* inDragItems, DragReference inDragRef, unsigned int inItemIndex,
FlavorType inFlavor, void** outData, unsigned int * outSize ) ;
nsresult ExtractDataFromOS ( DragReference inDragRef, ItemReference inItemRef, ResType inFlavor,
void** outBuffer, PRInt32* outBuffSize ) ;
// compute a screen rect from the frame associated with the given dom node
PRBool ComputeGlobalRectFromFrame ( nsIDOMNode* aDOMNode, Rect & outScreenRect ) ;
// callback for the MacOS DragManager when a drop site asks for data
static pascal OSErr DragSendDataProc ( FlavorType inFlavor, void* inRefCon,
ItemReference theItemRef, DragReference inDragRef ) ;
PRBool mImageDraggingSupported;
DragSendDataUPP mDragSendDataUPP;
DragReference mDragRef; // reference to _the_ drag. There can be only one.
nsISupportsArray* mDataItems; // cached here for when we start the drag so the
// DragSendDataProc has access to them.
// ONLY VALID DURING A DRAG STARTED WITHIN THIS APP.
}; // class nsDragService
#endif // nsDragService_h__

Просмотреть файл

@ -0,0 +1,600 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDynamicMDEF.h"
#include "prinrval.h"
#include "nsCOMPtr.h"
#include "nsIDOMElement.h"
#include "nsIDOMNode.h"
#include "nsMenuBar.h"
#include "nsIMenuBar.h"
#include "DefProcFakery.h"
#include "nsGUIEvent.h"
#include <Resources.h>
#include <MixedMode.h>
extern nsWeakPtr gMacMenubar;
// needed for CallMenuDefProc() to work correctly
#pragma options align=mac68k
// Caching the Mac menu
nsVoidArray gPreviousMenuHandleStack; // hold MenuHandles
nsMenuStack gPreviousMenuStack; // weak refs
nsWeakPtr gPreviousMenuBar; // weak ref
MenuHandle gSizedMenu = nsnull;
extern Handle gMDEF;
bool gTested = false;
MenuHandle gCachedMenuHandle = nsnull;
PRUint16 gCachedMenuID = 0;
extern PRInt16 gMenuDepth; // volital running total
extern PRInt16 gCurrentMenuDepth; // The menu depth that is currently shown
extern MenuHandle gLevel2HierMenu;
extern MenuHandle gLevel3HierMenu;
extern MenuHandle gLevel4HierMenu;
extern MenuHandle gLevel5HierMenu;
PRUint32 gCurrentMenuItem = 0; // 1 based ala MacOS
PRUint32 gCurrentTopLevelMenuIndex = 0;
MenuHandle gPreviousTopLevelMenuHandle = nsnull;
nsIMenu * gPreviousTopLevelMenu = nsnull;
nsIMenu * gPreviousMenu = nsnull;
MenuHandle gPreviousMenuHandle = nsnull;
//------------------------------------------------------------------------------
nsMenuStack::nsMenuStack()
{
}
nsMenuStack::~nsMenuStack()
{
}
nsresult
nsMenuStack::GetMenuAt(PRInt32 aIndex, nsIMenu **outMenu)
{
nsCOMPtr<nsISupports> elementPtr = getter_AddRefs(mMenuArray.ElementAt(aIndex));
if (!elementPtr)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(elementPtr);
return weakRef->QueryReferent(NS_GET_IID(nsIMenu), NS_REINTERPRET_CAST(void**, outMenu));
}
PRBool
nsMenuStack::HaveMenuAt(PRInt32 aIndex)
{
nsCOMPtr<nsISupports> elementPtr = getter_AddRefs(mMenuArray.ElementAt(aIndex));
if (!elementPtr)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(elementPtr);
nsCOMPtr<nsIMenu> theMenu = do_QueryReferent(weakRef);
return (theMenu.get() != nsnull);
}
PRBool nsMenuStack::RemoveMenuAt(PRInt32 aIndex)
{
return mMenuArray.RemoveElementAt(aIndex);
}
PRBool nsMenuStack::InsertMenuAt(nsIMenu* inMenuItem, PRInt32 aIndex)
{
nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(inMenuItem);
if (!weakRefFactory) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsISupports> observerRef = getter_AddRefs(NS_STATIC_CAST(nsISupports*, NS_GetWeakReference(weakRefFactory)));
if (!observerRef) return NS_ERROR_NULL_POINTER;
return mMenuArray.InsertElementAt(observerRef, aIndex);
}
#pragma mark -
//------------------------------------------------------------------------------
// Internal functions
void nsDynamicChooseItem(
MenuHandle theMenu,
Rect * menuRect,
Point hitPt,
short * whichItem);
void nsDynamicSizeTheMenu(
MenuHandle theMenu);
void nsBuildMenu(
MenuHandle theMenu,
PRBool isChild);
void nsPushMenu(
nsIMenu * aMenu);
void nsPopMenu(
nsIMenu ** aMenu);
void nsPushMenuHandle(
MenuHandle aMenu);
void nsPopMenuHandle(
MenuHandle * aMenu);
void nsCallSystemMDEF(
short message,
MenuHandle theMenu,
Rect * menuRect,
Point hitPt,
short * whichItem);
void nsDoMagic(
MenuHandle theMenu);
void nsPostBuild(
nsIMenu * menu,
MenuHandle theMenu,
PRBool isChild);
bool nsIsHierChild(
MenuHandle theMenu);
void nsCheckDestroy(
MenuHandle theMenu,
short * whichItem);
//void TestPreviousMenuStackUnwind(nsIMenu * aMenuJustBuilt, MenuHandle aMenuHandleJustBuilt);
//void TestCheckDestroy(MenuHandle theMenu, short * whichItem);
//void TestPostBuild(nsIMenu * menu, MenuHandle theMenu, PRBool isChild);
//------------------------------------------------------------------------------
pascal void nsDynamicMDEFMain(
short message,
MenuHandle theMenu,
Rect * menuRect,
Point hitPt,
short * whichItem)
{
switch (message) {
case kMenuDrawMsg:
//printf(" Draw passed in menu is = %d \n", *theMenu);
//printf(" t= %d l= %d b= %d r= %d\n", (*menuRect).top, (*menuRect).left, (*menuRect).bottom, (*menuRect).right);
//printf(" Point.v = %d Point.h = %d\n", hitPt.v, hitPt.h);
//printf(" whichItem = %d \n", *whichItem);
//printf(" theMenu.menuID = %d \n", (**theMenu).menuID);
nsCheckDestroy(theMenu, whichItem);
break;
case kMenuChooseMsg:
// Keep track of currently chosen item
nsDynamicChooseItem(theMenu, menuRect, hitPt, whichItem);
return; // Yes, intentional return as CallSystemMDEF has happened already
break;
case kMenuSizeMsg:
//printf("Size passed in menu is = %d \n", *theMenu);
//printf(" t= %d l= %d b= %d r= %d \n", (*menuRect).top, (*menuRect).left, (*menuRect).bottom ,(*menuRect).right);
//printf(" Point.v = %d Point.h = %d \n", hitPt.v, hitPt.h);
//printf(" whichItem = %d \n", *whichItem);
//printf(" theMenu.menuID = %d \n", (**theMenu).menuID);
nsCheckDestroy(theMenu, whichItem);
// Need to make sure that we rebuild the menu every time...
if (gPreviousMenuHandleStack.Count())
{
nsCOMPtr<nsIMenu> menu;
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, getter_AddRefs(menu));
// nsIMenu * menu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
MenuHandle menuHandle = (MenuHandle) gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1];
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
if( menu && menuHandle ) {
if( menuHandle == theMenu ) {
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menu));
if(listener) {
//printf("MenuPop \n");
nsMenuEvent mevent;
mevent.message = NS_MENU_SELECTED;
mevent.eventStructType = NS_MENU_EVENT;
mevent.point.x = 0;
mevent.point.y = 0;
mevent.widget = nsnull;
mevent.time = PR_IntervalNow();
mevent.mCommand = (PRUint32) nsnull;
// UNDO
listener->MenuDeselected(mevent);
//gPreviousMenuStack.RemoveElementAt(gPreviousMenuStack.Count() - 1);
gPreviousMenuStack.RemoveMenuAt(gPreviousMenuStack.Count() - 1);
//NS_IF_RELEASE(menu);
//printf("%d items now on gPreviousMenuStack \n", gPreviousMenuStack.Count());
gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1);
}
}
}
}
nsDynamicSizeTheMenu(theMenu);
break;
}
nsCallSystemMDEF(message, theMenu, menuRect, hitPt, whichItem);
// Force a size message next time we draw this menu
if(message == kMenuDrawMsg) {
#if !TARGET_CARBON
(**theMenu).menuWidth = -1;
(**theMenu).menuHeight = -1;
#endif
}
}
//------------------------------------------------------------------------------
void nsCheckDestroy(MenuHandle theMenu, short * whichItem)
{
// Determine if we have unselected the previous popup. If so we need to
// destroy it now.
bool changeOccured = true;
bool isChild = false;
if(gCurrentMenuItem == *whichItem)
changeOccured = false;
if(!gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1])
changeOccured = false;
if(nsIsHierChild(theMenu))
isChild = true;
if(changeOccured && !isChild) {
nsPreviousMenuStackUnwind(nsnull, theMenu);
if(gCurrentMenuDepth > 1)
gCurrentMenuDepth--;
}
}
//------------------------------------------------------------------------------
void nsDynamicChooseItem(
MenuHandle theMenu,
Rect * menuRect,
Point hitPt,
short * whichItem)
{
//printf("enter DynamicChooseItem \n");
nsCallSystemMDEF(kMenuChooseMsg, theMenu, menuRect, hitPt, whichItem);
nsCheckDestroy(theMenu, whichItem);
gCurrentMenuItem = *whichItem;
//printf("exit DynamicChooseItem \n");
}
//------------------------------------------------------------------------------
void nsDynamicSizeTheMenu(
MenuHandle theMenu)
{
//printf("enter DynamicSizeTheMenu \n");
nsDoMagic(theMenu);
//printf("exit DynamicSizeTheMenu \n");
}
//------------------------------------------------------------------------------
bool nsIsHierChild(MenuHandle theMenu)
{
if(theMenu == gLevel2HierMenu) {
if(gCurrentMenuDepth <= 2) return true;
} else if(theMenu == gLevel3HierMenu) {
if(gCurrentMenuDepth <= 3) return true;
} else if(theMenu == gLevel4HierMenu) {
if(gCurrentMenuDepth <= 4) return true;
} else if(theMenu == gLevel5HierMenu) {
if(gCurrentMenuDepth <= 5) return true;
}
return false;
}
//------------------------------------------------------------------------------
void nsDoMagic(MenuHandle theMenu)
{
//printf("DoMagic \n");
// ask if this is a child of the previous menu
PRBool isChild = PR_FALSE;
if (gPreviousMenuStack.Count() > 0)
{
if (gPreviousMenuStack.HaveMenuAt(gPreviousMenuStack.Count() - 1)) {
if(nsIsHierChild(theMenu)) {
isChild = PR_TRUE;
}
}
}
if(theMenu == gLevel2HierMenu) {
gCurrentMenuDepth = 2;
} else if(theMenu == gLevel3HierMenu) {
gCurrentMenuDepth = 3;
} else if(theMenu == gLevel4HierMenu) {
gCurrentMenuDepth = 4;
} else if(theMenu == gLevel5HierMenu) {
gCurrentMenuDepth = 5;
} else {
gCurrentMenuDepth = 1;
}
nsBuildMenu(theMenu, isChild);
}
//------------------------------------------------------------------------------
void nsBuildMenu(MenuHandle theMenu, PRBool isChild)
{
// printf("enter BuildMenu \n");
nsCOMPtr<nsIMenuBar> menubar = do_QueryReferent(gMacMenubar);
if (!menubar || !theMenu) {
return;
}
nsMenuEvent mevent;
mevent.message = NS_MENU_SELECTED;
mevent.eventStructType = NS_MENU_EVENT;
mevent.point.x = 0;
mevent.point.y = 0;
mevent.widget = nsnull;
mevent.time = PR_IntervalNow();
mevent.mCommand = (PRUint32) theMenu;
// If toplevel
if( gCurrentMenuDepth < 2 ) {
PRUint32 numMenus = 0;
menubar->GetMenuCount(numMenus);
numMenus--;
for(PRInt32 i = numMenus; i >= 0; i--) {
nsCOMPtr<nsIMenu> menu;
menubar->GetMenuAt(i, *getter_AddRefs(menu));
if(menu) {
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menu));
if(listener) {
// Reset menu depth count
gMenuDepth = 0;
nsEventStatus status = listener->MenuSelected(mevent);
if(status != nsEventStatus_eIgnore)
{
nsPostBuild(menu, theMenu, isChild);
gPreviousTopLevelMenuHandle = theMenu;
gPreviousTopLevelMenu = menu;
gPreviousMenuBar = getter_AddRefs(NS_GetWeakReference(menubar));
//printf("exit BuildMenu \n");
return;
}
}
}
}
} else {
// Not top level, so we can't use recursive MenuSelect <sigh>
// We must use the previously chosen menu item in combination
// with the current menu to determine what menu needs to be constructed
//printf("gCurrentMenuItem = %d \n", gCurrentMenuItem);
if (gCurrentMenuItem){
if (gPreviousMenuStack.Count() > 0)
{
nsCOMPtr<nsIMenu> prevMenu;
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, getter_AddRefs(prevMenu));
//nsIMenu * prevMenu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
//printf("gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count() );
if(prevMenu)
{
nsCOMPtr<nsISupports> supports;
prevMenu->GetItemAt(gCurrentMenuItem - 1, *getter_AddRefs(supports));
nsCOMPtr<nsIMenu> menu = do_QueryInterface(supports);
if (menu)
{
nsCOMPtr<nsIMenuListener> menulistener = do_QueryInterface(menu);
menulistener->MenuSelected(mevent);
nsPostBuild(menu, theMenu, isChild);
}
}
}
}
}
//printf("exit BuildMenu \n");
}
//------------------------------------------------------------------------------
void nsPostBuild(nsIMenu * menu, MenuHandle theMenu, PRBool isChild)
{
// it is built now
if(isChild || (gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1] != theMenu))
{
nsPushMenu(menu);
nsPushMenuHandle(theMenu);
//printf("Push: %d items in gMenuHandleStack \n", gMenuHandleStack.Count());
}
}
//------------------------------------------------------------------------------
void nsCallSystemMDEF(
short message,
MenuHandle theMenu,
Rect * menuRect,
Point hitPt,
short * whichItem)
{
// extract the real system mdef out of the fake one we've stored in the menu
Handle fakedMDEF = (**theMenu).menuProc;
Handle systemDefProc = DefProcFakery::GetSystemDefProc ( fakedMDEF );
SInt8 state = ::HGetState(systemDefProc);
::HLock(systemDefProc);
// can't use NewMenuDefProc() here because the routine descriptor has to use kM68kISA
CallMenuDefProc((RoutineDescriptorPtr)*systemDefProc, message, theMenu, menuRect, hitPt, whichItem);
::HSetState(systemDefProc, state);
return;
}
//------------------------------------------------------------------------------
void nsPushMenu(nsIMenu *aMenu)
{
gPreviousMenuStack.InsertMenuAt(aMenu, gPreviousMenuStack.Count());
}
//------------------------------------------------------------------------------
void nsPopMenu(nsIMenu ** aMenu)
{
if(gPreviousMenuStack.Count() > 0)
{
// *aMenu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, aMenu);
gPreviousMenuStack.RemoveMenuAt(gPreviousMenuStack.Count() - 1);
} else
*aMenu = nsnull;
}
//------------------------------------------------------------------------------
void nsPreviousMenuStackUnwind(nsIMenu * aMenuJustBuilt, MenuHandle aMenuHandleJustBuilt)
{
//PRBool shouldReleaseMenubar = PR_FALSE;
//printf("PreviousMenuStackUnwind called \n");
//printf("%d items on gPreviousMenuStack \n", gPreviousMenuStack.Count());
while (gPreviousMenuHandleStack.Count())
{
nsCOMPtr<nsIMenu> menu; // = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, getter_AddRefs(menu));
MenuHandle menuHandle = (MenuHandle) gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1];
if (menu)
{
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
if( menuHandle ) {
if( menuHandle != aMenuHandleJustBuilt ) {
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menu));
if(listener) {
nsMenuEvent mevent;
mevent.message = NS_MENU_SELECTED;
mevent.eventStructType = NS_MENU_EVENT;
mevent.point.x = 0;
mevent.point.y = 0;
mevent.widget = nsnull;
mevent.time = PR_IntervalNow();
mevent.mCommand = (PRUint32) nsnull;
// UNDO
listener->MenuDeselected(mevent);
//gPreviousMenuStack.RemoveElementAt(gPreviousMenuStack.Count() - 1);
gPreviousMenuStack.RemoveMenuAt(gPreviousMenuStack.Count() - 1);
// NS_IF_RELEASE(menu);
//shouldReleaseMenubar = PR_TRUE;
//printf("%d items now on gPreviousMenuStack \n", gPreviousMenuStack.Count());
gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1);
}
}
else {
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
// we are the aMenuHandleJustBuilt
return;
}
}
}
else
{
// remove the weak ref
gPreviousMenuStack.RemoveMenuAt(gPreviousMenuStack.Count() - 1);
NS_ASSERTION(menuHandle != aMenuHandleJustBuilt, "Got the menu handle just built");
if( menuHandle )
gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1);
}
}
// relinquish hold of the menubar _after_ releasing the menu so it can finish
// unregistering itself.
//if ( shouldReleaseMenubar )
// gPreviousMenuBar = nsnull;
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
}
//------------------------------------------------------------------------------
void nsPushMenuHandle(MenuHandle aMenu)
{
gPreviousMenuHandleStack.AppendElement(aMenu);
}
//------------------------------------------------------------------------------
void nsPopMenuHandle(MenuHandle * aMenu)
{
*aMenu = (MenuHandle) gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1];
gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1);
}
#pragma options align=reset

Просмотреть файл

@ -0,0 +1,125 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// MDEF for doing dynamic menu construction
#ifndef nsDynamicMDEF_h__
#define nsDynamicMDEF_h__
#include "nsSupportsArray.h"
#include "nsIMenu.h"
#include <Menus.h>
pascal void nsDynamicMDEFMain(
short message,
MenuHandle theMenu,
Rect * menuRect,
Point hitPt,
short * whichItem);
void nsPreviousMenuStackUnwind(
nsIMenu * aMenuJustBuilt,
MenuHandle aMenuHandleJustBuilt);
// helper class useful for counting instances
class nsInstanceCounter
{
public:
nsInstanceCounter(const char* inDesc)
: mInstanceCount(0)
, mDescription(inDesc)
{
}
~nsInstanceCounter()
{
printf("%s %ld\n", mDescription, mInstanceCount);
}
nsInstanceCounter& operator ++() // prefix
{
++ mInstanceCount;
return *this;
}
nsInstanceCounter& operator -- () // prefix
{
-- mInstanceCount;
return *this;
}
protected:
PRInt32 mInstanceCount;
const char* mDescription;
};
//------------------------------------------------------------------------------
class nsMenuStack
{
public:
nsMenuStack();
~nsMenuStack();
PRInt32 Count()
{
PRUint32 num;
mMenuArray.Count(&num);
return (PRInt32)num;
}
// returns addreffed nsIMenu
nsresult GetMenuAt(PRInt32 aIndex, nsIMenu **outMenu);
PRBool HaveMenuAt(PRInt32 aIndex);
PRBool RemoveMenuAt(PRInt32 aIndex); // no release
PRBool InsertMenuAt(nsIMenu* aElement, PRInt32 aIndex); // no addrefs; weak ref.
protected:
nsSupportsArray mMenuArray; // array of weak refs to nsIMenus
};
#endif nsDynamicMDEF_h__

Просмотреть файл

@ -0,0 +1,734 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsCOMPtr.h"
#include "nsReadableUtils.h"
#include "nsNetUtil.h"
#include "nsIComponentManager.h"
#include "nsILocalFile.h"
#ifndef XP_MACOSX
#include "nsILocalFileMac.h"
#endif
#include "nsIURL.h"
#include "nsVoidArray.h"
#include "nsIFileChannel.h"
#include <InternetConfig.h>
#include "nsCarbonHelpers.h"
#include "nsFilePicker.h"
#include "nsWatchTask.h"
#include "nsIInternetConfigService.h"
#include "nsIMIMEInfo.h"
#include "nsIPlatformCharset.h"
#include "nsICharsetConverterManager.h"
//
// copied over from nsMacControl since we it's not being built.
//
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
static void GetFileSystemCharset(nsString & fileSystemCharset);
static void GetFileSystemCharset(nsString & fileSystemCharset)
{
static nsAutoString aCharset;
nsresult rv;
if (aCharset.Length() < 1) {
nsCOMPtr <nsIPlatformCharset> platformCharset = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, aCharset);
NS_ASSERTION(NS_SUCCEEDED(rv), "error getting platform charset");
if (NS_FAILED(rv))
aCharset.AssignWithConversion("x-mac-roman");
}
fileSystemCharset = aCharset;
}
static void StringToStr255(const nsString& aText, Str255& aStr255) ;
static void StringToStr255(const nsString& aText, Str255& aStr255)
{
static nsIUnicodeEncoder* sUnicodeEncoder = nsnull;
nsresult rv = NS_OK;
// get file system charset and create a unicode encoder
if (!sUnicodeEncoder) {
nsAutoString fileSystemCharset;
GetFileSystemCharset(fileSystemCharset);
nsCOMPtr<nsICharsetConverterManager> ccm =
do_GetService(kCharsetConverterManagerCID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = ccm->GetUnicodeEncoder(&fileSystemCharset, &sUnicodeEncoder);
if (NS_SUCCEEDED(rv)) {
rv = sUnicodeEncoder->SetOutputErrorBehavior(nsIUnicodeEncoder::kOnError_Replace, nsnull, (PRUnichar)'?');
}
}
}
// converts from unicode to the file system charset
if (NS_SUCCEEDED(rv)) {
PRInt32 inLength = aText.Length();
PRInt32 outLength = 255;
rv = sUnicodeEncoder->Convert(aText.get(), &inLength, (char *) &aStr255[1], &outLength);
if (NS_SUCCEEDED(rv))
aStr255[0] = outLength;
}
if (NS_FAILED(rv)) {
// NS_ASSERTION(0, "error: charset covnersion");
NS_LossyConvertUCS2toASCII buffer(Substring(aText,0,254));
PRInt32 len = buffer.Length();
memcpy(&aStr255[1], buffer.get(), len);
aStr255[0] = len;
}
}
NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
//-------------------------------------------------------------------------
//
// nsFilePicker constructor
//
//-------------------------------------------------------------------------
nsFilePicker::nsFilePicker()
: mAllFilesDisplayed(PR_TRUE)
{
NS_INIT_REFCNT();
// Zero out the type lists
for (int i = 0; i < kMaxTypeListCount; i++)
mTypeLists[i] = 0L;
}
//-------------------------------------------------------------------------
//
// nsFilePicker destructor
//
//-------------------------------------------------------------------------
nsFilePicker::~nsFilePicker()
{
// Destroy any filters we have built
if ( mFilters.Count() ) {
for (int i = 0; i < kMaxTypeListCount; i++) {
if (mTypeLists[i])
DisposePtr((Ptr)mTypeLists[i]);
}
}
mFilters.Clear();
mTitles.Clear();
}
NS_IMETHODIMP
nsFilePicker::InitNative(nsIWidget *aParent, const PRUnichar *aTitle, PRInt16 aMode)
{
mTitle = aTitle;
mMode = aMode;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Ok's the dialog
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::OnOk()
{
mWasCancelled = PR_FALSE;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Cancel the dialog
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::OnCancel()
{
mWasCancelled = PR_TRUE;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Show - Display the file dialog
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
{
NS_ENSURE_ARG_POINTER(retval);
*retval = returnCancel;
nsString filterList;
char *filterBuffer = ToNewCString(filterList);
Str255 title;
Str255 defaultName;
StringToStr255(mTitle,title);
StringToStr255(mDefault,defaultName);
FSSpec theFile;
PRInt16 userClicksOK = returnCancel;
// XXX Ignore the filter list for now....
if (mMode == modeOpen)
userClicksOK = GetLocalFile(title, &theFile);
else if (mMode == modeSave)
userClicksOK = PutLocalFile(title, defaultName, &theFile);
else if (mMode == modeGetFolder)
userClicksOK = GetLocalFolder(title, &theFile);
// Clean up filter buffers
delete[] filterBuffer;
#ifndef XP_MACOSX
if (userClicksOK == returnOK || userClicksOK == returnReplace)
{
nsCOMPtr<nsILocalFile> localFile(do_CreateInstance("@mozilla.org/file/local;1"));
nsCOMPtr<nsILocalFileMac> macFile(do_QueryInterface(localFile));
nsresult rv = macFile->InitWithFSSpec(&theFile);
if (NS_FAILED(rv)) return rv;
mFile = do_QueryInterface(macFile);
}
#endif
*retval = userClicksOK;
return NS_OK;
}
//
// FileDialogEventHandlerProc
//
// An event filter proc for NavServices so the dialogs will be movable-modals.
//
static pascal void FileDialogEventHandlerProc( NavEventCallbackMessage msg, NavCBRecPtr cbRec, NavCallBackUserData data )
{
#if 0
switch ( msg ) {
case kNavCBEvent:
switch ( cbRec->eventData.eventDataParms.event->what ) {
case updateEvt:
WindowPtr window = reinterpret_cast<WindowPtr>(cbRec->eventData.eventDataParms.event->message);
nsMacWindow* macWindow = nsMacMessageSink::GetNSWindowFromMacWindow(window);
::BeginUpdate(window);
if (macWindow) {
EventRecord theEvent = *cbRec->eventData.eventDataParms.event;
macWindow->HandleOSEvent(theEvent);
}
::EndUpdate(window);
break;
}
break;
}
#endif
}
//
// IsFileInFilterList
//
// Check our |mTypeLists| list to see if the given type is in there.
//
Boolean
nsFilePicker :: IsTypeInFilterList ( ResType inType )
{
for ( int i = 0; i < mFilters.Count(); ++i ) {
for ( int j = 0; j < mTypeLists[i]->osTypeCount; ++j ) {
if ( mTypeLists[i]->osType[j] == inType )
return true;
} // foreach type w/in the group
} // for each filter group
return false;
} // IsFileInFilterList
Boolean
nsFilePicker :: IsExtensionInFilterList ( StrFileName & inFileName )
{
char extension[256];
// determine the extension from the file name
unsigned char* curr = &inFileName[inFileName[0]];
while ( curr != inFileName && *curr-- != '.' ) ;
if ( curr == inFileName ) // no '.' in string, fails this check
return false;
++curr; // we took one too many steps back
short extensionLen = (inFileName + inFileName[0]) - curr + 1;
strncpy ( extension, (char*)curr, extensionLen);
extension[extensionLen] = '\0';
// see if it is in our list
for ( int i = 0; i < mFlatFilters.Count(); ++i ) {
if ( mFlatFilters[i]->Equals(extension) )
return true;
}
return false;
}
//
// FileDialogFilterProc
//
// Called from navServices with our filePicker object as |callbackUD|, check our
// internal list to see if the file should be displayed.
//
pascal
Boolean
nsFilePicker :: FileDialogFilterProc ( AEDesc* theItem, void* theInfo,
NavCallBackUserData callbackUD, NavFilterModes filterMode )
{
Boolean shouldDisplay = true;
nsFilePicker* self = NS_REINTERPRET_CAST(nsFilePicker*, callbackUD);
if ( self && !self->mAllFilesDisplayed ) {
if ( theItem->descriptorType == typeFSS ) {
NavFileOrFolderInfo* info = NS_REINTERPRET_CAST ( NavFileOrFolderInfo*, theInfo );
if ( !info->isFolder ) {
// check it against our list. If that fails, check the extension directly
if ( ! self->IsTypeInFilterList(info->fileAndFolder.fileInfo.finderInfo.fdType) ) {
FSSpec fileSpec;
if ( ::AEGetDescData(theItem, &fileSpec, sizeof(FSSpec)) == noErr )
if ( ! self->IsExtensionInFilterList(fileSpec.name) )
shouldDisplay = false;
}
} // if file isn't a folder
} // if the item is an FSSpec
}
return shouldDisplay;
} // FileDialogFilterProc
//-------------------------------------------------------------------------
//
// GetFile
//
// Use NavServices to do a GetFile. Returns PR_TRUE if the user presses OK in the dialog. If
// they do so, the selected file is in the FSSpec.
//
//-------------------------------------------------------------------------
PRInt16
nsFilePicker::GetLocalFile(Str255 & inTitle, /* filter list here later */ FSSpec* outSpec)
{
PRInt16 retVal = returnCancel;
NavReplyRecord reply;
NavDialogOptions dialogOptions;
NavEventUPP eventProc = NewNavEventUPP(FileDialogEventHandlerProc); // doesn't really matter if this fails
NavObjectFilterUPP filterProc = NewNavObjectFilterUPP(FileDialogFilterProc); // doesn't really matter if this fails
OSErr anErr = NavGetDefaultDialogOptions(&dialogOptions);
if (anErr == noErr) {
// Set the options for how the get file dialog will appear
dialogOptions.dialogOptionFlags |= kNavNoTypePopup;
dialogOptions.dialogOptionFlags |= kNavDontAutoTranslate;
dialogOptions.dialogOptionFlags |= kNavDontAddTranslateItems;
dialogOptions.dialogOptionFlags ^= kNavAllowMultipleFiles;
::BlockMoveData(inTitle, dialogOptions.windowTitle, *inTitle + 1);
// sets up the |mTypeLists| array so the filter proc can use it
MapFilterToFileTypes();
// allow packages to be chosen if the filter is "*"
if ( mAllFilesDisplayed )
dialogOptions.dialogOptionFlags |= kNavSupportPackages;
// Display the get file dialog. Only use a filter proc if there are any
// filters registered.
nsWatchTask::GetTask().Suspend();
anErr = ::NavGetFile(
NULL,
&reply,
&dialogOptions,
eventProc,
NULL, // preview proc
mFilters.Count() ? filterProc : NULL,
NULL, //typeList,
this); // callbackUD - used by the filterProc
nsWatchTask::GetTask().Resume();
// See if the user has selected save
if (anErr == noErr && reply.validRecord) {
AEKeyword theKeyword;
DescType actualType;
Size actualSize;
FSSpec theFSSpec;
// Get the FSSpec for the file to be opened
anErr = AEGetNthPtr(&(reply.selection), 1, typeFSS, &theKeyword, &actualType,
&theFSSpec, sizeof(theFSSpec), &actualSize);
if (anErr == noErr)
{
*outSpec = theFSSpec; // Return the FSSpec
retVal = returnOK;
// Some housekeeping for Nav Services
::NavDisposeReply(&reply);
}
} // if user clicked OK
} // if can get dialog options
if ( eventProc )
::DisposeNavEventUPP(eventProc);
return retVal;
} // GetFile
//-------------------------------------------------------------------------
//
// GetFolder
//
// Use NavServices to do a PutFile. Returns PR_TRUE if the user presses OK in the dialog. If
// they do so, the folder location is in the FSSpec.
//
//-------------------------------------------------------------------------
PRInt16
nsFilePicker::GetLocalFolder(Str255 & inTitle, FSSpec* outSpec)
{
PRInt16 retVal = returnCancel;
NavReplyRecord reply;
NavDialogOptions dialogOptions;
NavEventUPP eventProc = NewNavEventUPP(FileDialogEventHandlerProc); // doesn't really matter if this fails
OSErr anErr = NavGetDefaultDialogOptions(&dialogOptions);
if (anErr == noErr) {
// Set the options for how the get file dialog will appear
dialogOptions.dialogOptionFlags |= kNavNoTypePopup;
dialogOptions.dialogOptionFlags |= kNavDontAutoTranslate;
dialogOptions.dialogOptionFlags |= kNavDontAddTranslateItems;
dialogOptions.dialogOptionFlags ^= kNavAllowMultipleFiles;
::BlockMoveData(inTitle, dialogOptions.windowTitle, *inTitle + 1);
// Display the get file dialog
nsWatchTask::GetTask().Suspend();
anErr = ::NavChooseFolder(
NULL,
&reply,
&dialogOptions,
eventProc,
NULL, // filter proc
NULL); // callbackUD
nsWatchTask::GetTask().Resume();
// See if the user has selected save
if (anErr == noErr && reply.validRecord) {
AEKeyword theKeyword;
DescType actualType;
Size actualSize;
FSSpec theFSSpec;
// Get the FSSpec for the file to be opened
anErr = AEGetNthPtr(&(reply.selection), 1, typeFSS, &theKeyword, &actualType,
&theFSSpec, sizeof(theFSSpec), &actualSize);
if (anErr == noErr) {
*outSpec = theFSSpec; // Return the FSSpec
retVal = returnOK;
// Some housekeeping for Nav Services
::NavDisposeReply(&reply);
}
} // if user clicked OK
} // if can get dialog options
if ( eventProc )
::DisposeNavEventUPP(eventProc);
return retVal;
} // GetFolder
PRInt16
nsFilePicker::PutLocalFile(Str255 & inTitle, Str255 & inDefaultName, FSSpec* outFileSpec)
{
PRInt16 retVal = returnCancel;
NavReplyRecord reply;
NavDialogOptions dialogOptions;
NavEventUPP eventProc = NewNavEventUPP(FileDialogEventHandlerProc); // doesn't really matter if this fails
OSType typeToSave = 'TEXT';
OSType creatorToSave = 'MOZZ';
OSErr anErr = NavGetDefaultDialogOptions(&dialogOptions);
if (anErr == noErr) {
// Set the options for how the get file dialog will appear
dialogOptions.dialogOptionFlags |= kNavNoTypePopup;
dialogOptions.dialogOptionFlags |= kNavDontAutoTranslate;
dialogOptions.dialogOptionFlags |= kNavDontAddTranslateItems;
dialogOptions.dialogOptionFlags ^= kNavAllowMultipleFiles;
::BlockMoveData(inTitle, dialogOptions.windowTitle, *inTitle + 1);
::BlockMoveData(inDefaultName, dialogOptions.savedFileName, *inDefaultName + 1);
// Display the get file dialog
nsWatchTask::GetTask().Suspend();
anErr = ::NavPutFile(
NULL,
&reply,
&dialogOptions,
eventProc,
typeToSave,
creatorToSave,
NULL); // callbackUD
nsWatchTask::GetTask().Resume();
// See if the user has selected save
if (anErr == noErr && reply.validRecord)
{
AEKeyword theKeyword;
DescType actualType;
Size actualSize;
FSSpec theFSSpec;
// Get the FSSpec for the file to be opened
anErr = AEGetNthPtr(&(reply.selection), 1, typeFSS, &theKeyword, &actualType,
&theFSSpec, sizeof(theFSSpec), &actualSize);
if (anErr == noErr) {
*outFileSpec = theFSSpec; // Return the FSSpec
if (reply.replacing)
retVal = returnReplace;
else
retVal = returnOK;
// Some housekeeping for Nav Services
::NavCompleteSave(&reply, kNavTranslateInPlace);
::NavDisposeReply(&reply);
}
} // if user clicked OK
} // if can get dialog options
if ( eventProc )
::DisposeNavEventUPP(eventProc);
return retVal;
}
//
// MapFilterToFileTypes
//
// Take the list of file types (in a nice win32-specific format) and ask IC to give us
// the MacOS file type codes for them.
//
void
nsFilePicker :: MapFilterToFileTypes ( )
{
nsCOMPtr<nsIInternetConfigService> icService ( do_GetService(NS_INTERNETCONFIGSERVICE_CONTRACTID) );
NS_ASSERTION(icService, "Can't get InternetConfig Service, bailing out");
if ( !icService ) {
// We couldn't get the IC Service, bail. Since |mAllFilesDisplayed| is still
// set, the dialog will allow selection of all files.
return;
}
if (mFilters.Count())
{
// First we allocate the memory for the Mac type lists
for (PRUint32 loop1 = 0; loop1 < mFilters.Count() && loop1 < kMaxTypeListCount; loop1++)
{
mTypeLists[loop1] =
(NavTypeListPtr)NewPtrClear(sizeof(NavTypeList) + kMaxTypesPerFilter * sizeof(OSType));
if ( !mTypeLists[loop1] )
return; // don't worry, we'll clean up in the dtor
}
// Now loop through each of the filter strings
for (PRUint32 loop1 = 0; loop1 < mFilters.Count(); loop1++)
{
const nsString& filterWide = *mFilters[loop1];
char* filter = ToNewCString(filterWide);
NS_ASSERTION ( filterWide.Length(), "Oops. filepicker.properties not correctly installed");
if ( filterWide.Length() && filter )
{
PRUint32 filterIndex = 0; // Index into the filter string
PRUint32 typeTempIndex = 0; // Index into the temp string for a single filter type
PRUint32 typesInThisFilter = 0; // Count for # of types in this filter
bool finishedThisFilter = false; // Flag so we know when we're finsihed with the filter
char typeTemp[256];
char tempChar; // char we're currently looking at
// Loop through the characters of filter string. Every time we get to a
// semicolon (or a null, meaning we've hit the end of the full string)
// then we've found the filter and can pass it off to IC to get a macOS
// file type out of it.
do
{
tempChar = filter[filterIndex];
if ((tempChar == ';') || (tempChar == 0)) { // End of filter type reached
typeTemp[typeTempIndex] = '\0'; // null terminate
// to make it easier to match file extensions while we're filtering, flatten
// out the list. Ignore filters that are just "*" and also remove the
// leading "*" from filters we do add.
if ( strlen(typeTemp) > 1 )
mFlatFilters.AppendCString ( nsCString((char*)&typeTemp[1]) ); // cut out the "*"
// ask IC if it's not "all files" (designated by "*")
if ( !(typeTemp[1] == '\0' && typeTemp[0] == '*') ) {
mAllFilesDisplayed = PR_FALSE;
nsCOMPtr<nsIMIMEInfo> icEntry;
icService->GetMIMEInfoFromExtension(typeTemp, getter_AddRefs(icEntry));
if ( icEntry )
{
bool addToList = true;
OSType tempOSType;
icEntry->GetMacType(NS_REINTERPRET_CAST(PRUint32*, (&tempOSType)));
for (PRUint32 typeIndex = 0; typeIndex < typesInThisFilter; typeIndex++)
{
if (mTypeLists[loop1]->osType[typeIndex] == tempOSType)
{
addToList = false;
break;
}
}
if (addToList && typesInThisFilter < kMaxTypesPerFilter)
mTypeLists[loop1]->osType[typesInThisFilter++] = tempOSType;
}
} // if not "*"
typeTempIndex = 0; // Reset the temp string for the type
if (tempChar == '\0')
finishedThisFilter = true;
}
else
{
// strip out whitespace as we go
if ( tempChar != ' ' )
typeTemp[typeTempIndex++] = tempChar;
}
filterIndex++;
} while (!finishedThisFilter);
// Set how many OSTypes we actually found
mTypeLists[loop1]->osTypeCount = typesInThisFilter;
nsMemory :: Free ( NS_REINTERPRET_CAST(void*, filter) );
}
}
}
} // MapFilterToFileTypes
NS_IMETHODIMP nsFilePicker::GetFile(nsILocalFile **aFile)
{
NS_ENSURE_ARG_POINTER(aFile);
NS_IF_ADDREF(*aFile = mFile);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetFileURL(nsIFileURL **aFileURL)
{
NS_ENSURE_TRUE(mFile, NS_ERROR_FAILURE);
nsCOMPtr<nsIURI> uri;
NS_NewFileURI(getter_AddRefs(uri), mFile);
nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(uri));
NS_ENSURE_TRUE(fileURL, NS_ERROR_FAILURE);
NS_ADDREF(*aFileURL = fileURL);
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the file + path
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::SetDefaultString(const PRUnichar *aString)
{
mDefault = aString;
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
{
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// Set the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::SetDisplayDirectory(nsILocalFile *aDirectory)
{
mDisplayDirectory = aDirectory;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetDisplayDirectory(nsILocalFile **aDirectory)
{
*aDirectory = mDisplayDirectory;
NS_IF_ADDREF(*aDirectory);
return NS_OK;
}
NS_IMETHODIMP
nsFilePicker::AppendFilter(const PRUnichar *aTitle, const PRUnichar *aFilter)
{
mFilters.AppendString(nsDependentString(aFilter));
mTitles.AppendString(nsDependentString(aTitle));
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2000 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef nsFilePicker_h__
#define nsFilePicker_h__
#include "nsBaseFilePicker.h"
#include "nsString.h"
#include "nsIFileChannel.h"
#include "nsILocalFile.h"
#include <Navigation.h>
#define kMaxTypeListCount 10
#define kMaxTypesPerFilter 9
/**
* Native Mac FileSelector wrapper
*/
class nsFilePicker : public nsBaseFilePicker
{
public:
nsFilePicker();
virtual ~nsFilePicker();
NS_DECL_ISUPPORTS
// nsIFilePicker (less what's in nsBaseFilePicker)
NS_IMETHOD GetDefaultString(PRUnichar * *aDefaultString);
NS_IMETHOD SetDefaultString(const PRUnichar * aDefaultString);
NS_IMETHOD GetDisplayDirectory(nsILocalFile * *aDisplayDirectory);
NS_IMETHOD SetDisplayDirectory(nsILocalFile * aDisplayDirectory);
NS_IMETHOD GetFile(nsILocalFile * *aFile);
NS_IMETHOD GetFileURL(nsIFileURL * *aFileURL);
NS_IMETHOD Show(PRInt16 *_retval);
NS_IMETHOD AppendFilter(const PRUnichar *aTitle, const PRUnichar *aFilter) ;
protected:
NS_IMETHOD InitNative(nsIWidget *aParent, const PRUnichar *aTitle, PRInt16 aMode);
NS_IMETHOD OnOk();
NS_IMETHOD OnCancel();
// actual implementations of get/put dialogs using NavServices
PRInt16 PutLocalFile(Str255 & inTitle, Str255 & inDefaultName, FSSpec* outFileSpec) ;
PRInt16 GetLocalFile(Str255 & inTitle, FSSpec* outFileSpec);
PRInt16 GetLocalFolder(Str255 & inTitle, FSSpec* outFileSpec);
void MapFilterToFileTypes ( ) ;
Boolean IsTypeInFilterList ( ResType inType ) ;
Boolean IsExtensionInFilterList ( StrFileName & inFileName ) ;
// filter routine for file types
static pascal Boolean FileDialogFilterProc ( AEDesc* theItem, void* info,
NavCallBackUserData callbackUD,
NavFilterModes filterMode ) ;
PRBool mWasCancelled;
PRBool mAllFilesDisplayed;
nsString mTitle;
PRInt16 mMode;
nsCOMPtr<nsILocalFile> mFile;
nsString mDefault;
nsCOMPtr<nsILocalFile> mDisplayDirectory;
nsStringArray mFilters;
nsStringArray mTitles;
nsCStringArray mFlatFilters; // all the filters from mFilters, but one per string
NavTypeListPtr mTypeLists[kMaxTypeListCount];
};
#endif // nsFilePicker_h__

Просмотреть файл

@ -0,0 +1,589 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsLookAndFeel.h"
#include "nsXPLookAndFeel.h"
#include "nsCarbonHelpers.h"
#include "nsIInternetConfigService.h"
#include "nsIServiceManager.h"
#include "nsSize.h"
//-------------------------------------------------------------------------
//
// Query interface implementation
//
//-------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(nsLookAndFeel, nsILookAndFeel);
nsLookAndFeel::nsLookAndFeel()
{
NS_INIT_REFCNT();
(void)NS_NewXPLookAndFeel(getter_AddRefs(mXPLookAndFeel));
}
nsLookAndFeel::~nsLookAndFeel()
{
}
NS_IMETHODIMP nsLookAndFeel::GetColor(const nsColorID aID, nscolor &aColor)
{
nsresult res = NS_OK;
if (mXPLookAndFeel)
{
res = mXPLookAndFeel->GetColor(aID, aColor);
if (NS_SUCCEEDED(res))
return res;
res = NS_OK;
}
switch (aID) {
case eColor_WindowBackground:
{
nsCOMPtr<nsIInternetConfigService> icService_wb (do_GetService(NS_INTERNETCONFIGSERVICE_CONTRACTID));
if (icService_wb)
{
res = icService_wb->GetColor(nsIInternetConfigService::eICColor_WebBackgroundColour, &aColor);
if (NS_SUCCEEDED(res))
return res;
}
aColor = NS_RGB(0xff,0xff,0xff); // default to white if we didn't find it in internet config
res = NS_OK;
}
break;
case eColor_WindowForeground:
aColor = NS_RGB(0x00,0x00,0x00);
break;
case eColor_WidgetBackground:
aColor = NS_RGB(0xdd,0xdd,0xdd);
break;
case eColor_WidgetForeground:
aColor = NS_RGB(0x00,0x00,0x00);
break;
case eColor_WidgetSelectBackground:
aColor = NS_RGB(0x80,0x80,0x80);
break;
case eColor_WidgetSelectForeground:
aColor = NS_RGB(0x00,0x00,0x80);
break;
case eColor_Widget3DHighlight:
aColor = NS_RGB(0xa0,0xa0,0xa0);
break;
case eColor_Widget3DShadow:
aColor = NS_RGB(0x40,0x40,0x40);
break;
case eColor_TextBackground:
aColor = NS_RGB(0xff,0xff,0xff);
break;
case eColor_TextForeground:
{
nsCOMPtr<nsIInternetConfigService> icService_tf (do_GetService(NS_INTERNETCONFIGSERVICE_CONTRACTID));
if (icService_tf)
{
res = icService_tf->GetColor(nsIInternetConfigService::eICColor_WebTextColor, &aColor);
if (NS_SUCCEEDED(res))
return res;
}
aColor = NS_RGB(0x00,0x00,0x00);
res = NS_OK;
}
break;
case eColor_highlight: // CSS2 color
case eColor_TextSelectBackground:
RGBColor macColor;
GrafPtr thePort;
::GetPort(&thePort);
if (thePort)
{
::GetPortHiliteColor(thePort,&macColor);
aColor = NS_RGB(macColor.red>>8, macColor.green>>8, macColor.blue>>8);
}
else
aColor = NS_RGB(0x00,0x00,0x00);
break;
case eColor_highlighttext: // CSS2 color
case eColor_TextSelectForeground:
GetColor(eColor_TextSelectBackground, aColor);
if (aColor == 0x000000)
aColor = NS_RGB(0xff,0xff,0xff);
else
aColor = NS_DONT_CHANGE_COLOR;
break;
//
// css2 system colors http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
//
// It's really hard to effectively map these to the Appearance Manager properly,
// since they are modeled word for word after the win32 system colors and don't have any
// real counterparts in the Mac world. I'm sure we'll be tweaking these for
// years to come.
//
// Thanks to mpt26@student.canterbury.ac.nz for the hardcoded values that form the defaults
// if querying the Appearance Manager fails ;)
//
case eColor_buttontext:
res = GetMacTextColor(kThemeTextColorPushButtonActive, aColor, NS_RGB(0x00,0x00,0x00));
break;
case eColor_captiontext:
res = GetMacTextColor(kThemeTextColorWindowHeaderActive, aColor, NS_RGB(0x00,0x00,0x00));
break;
case eColor_menutext:
res = GetMacTextColor(kThemeTextColorMenuItemActive, aColor, NS_RGB(0x00,0x00,0x00));
break;
case eColor_infotext:
//this will only work on MacOS 9. Mac OS < 9 will use hardcoded value
res = GetMacTextColor(kThemeTextColorNotification, aColor, NS_RGB(0x00,0x00,0x00));
break;
case eColor_windowtext:
//DialogActive is closest match to "windowtext"
res = GetMacTextColor(kThemeTextColorDialogActive, aColor, NS_RGB(0x00,0x00,0x00));
break;
case eColor_activecaption:
//no way to fetch this colour. HARDCODING to Platinum
//res = GetMacBrushColor(??, aColor, NS_RGB(0xCC,0xCC,0xCC));
//active titlebar etc is #CCCCCC
aColor = NS_RGB(0xCC,0xCC,0xCC);
res = NS_OK;
break;
case eColor_activeborder:
//If it means anything at all on Mac OS, then its black in every theme I've tried,
//but Aqua *has* no border!
res = GetMacBrushColor(kThemeBrushBlack, aColor, NS_RGB(0x00,0x00,0x00));
break;
case eColor_appworkspace:
// NOTE: this is an MDI color and does not exist on macOS.
//used the closest match, which will likely be white.
res = GetMacBrushColor(kThemeBrushDocumentWindowBackground, aColor, NS_RGB(0x63,0x63,0xCE));
break;
case eColor_background:
// NOTE: chances are good this is a pattern, not a pure color. What do we do?
// Seconded. This is almost never going to be a flat colour...
//incidentally, this is supposed to be the colour of the desktop, though how anyone
//is supposed to guess that from the name?
aColor = NS_RGB(0x63,0x63,0xCE);
res = NS_OK;
break;
case eColor_buttonface:
res = GetMacBrushColor(kThemeBrushButtonFaceActive, aColor, NS_RGB(0xDD,0xDD,0xDD));
break;
case eColor_buttonhighlight:
//lighter of 2 possible highlight colours available
res = GetMacBrushColor(kThemeBrushButtonActiveLightHighlight, aColor, NS_RGB(0xFF,0xFF,0xFF));
break;
case eColor_buttonshadow:
//darker of 2 possible shadow colours available
res = GetMacBrushColor(kThemeBrushButtonActiveDarkShadow, aColor, NS_RGB(0x77,0x77,0x77));
break;
case eColor_graytext:
res = GetMacTextColor(kThemeTextColorDialogInactive, aColor, NS_RGB(0x77,0x77,0x77));
break;
case eColor_inactiveborder:
//ScrollBar DelimiterInactive looks like an odd constant to use, but gives the right colour in most themes,
//also if you look at where this colour is *actually* used, it is pretty much what we want
res = GetMacBrushColor(kThemeBrushScrollBarDelimiterInactive, aColor, NS_RGB(0x55,0x55,0x55));
break;
case eColor_inactivecaption:
//best guess. Usually right in most themes I think
res = GetMacBrushColor(kThemeBrushDialogBackgroundInactive, aColor, NS_RGB(0xDD,0xDD,0xDD));
break;
case eColor_inactivecaptiontext:
res = GetMacTextColor(kThemeTextColorWindowHeaderInactive, aColor, NS_RGB(0x77,0x77,0x77));
break;
case eColor_scrollbar:
//this is the scrollbar trough. HARDCODING no way to get this colour
//res = GetMacBrushColor(??, aColor, NS_RGB(0xAA,0xAA,0xAA));
aColor = NS_RGB(0xAA,0xAA,0xAA);
res = NS_OK;
break;
case eColor_threeddarkshadow:
res = GetMacBrushColor(kThemeBrushButtonActiveDarkShadow, aColor, NS_RGB(0x77,0x77,0x77));
break;
case eColor_threedshadow:
res = GetMacBrushColor(kThemeBrushButtonActiveLightShadow, aColor, NS_RGB(0x99,0x99,0x99));
break;
case eColor_threedface:
res = GetMacBrushColor(kThemeBrushButtonFaceActive, aColor, NS_RGB(0xDD,0xDD,0xDD));
break;
case eColor_threedhighlight:
res = GetMacBrushColor(kThemeBrushButtonActiveLightHighlight, aColor, NS_RGB(0xFF,0xFF,0xFF));
break;
case eColor_threedlightshadow:
//the description in the CSS2 spec says this is on the side facing the lightsource,
//so its not a shadow in Mac OS terms, its the darker of the highlights
res = GetMacBrushColor(kThemeBrushButtonActiveDarkHighlight, aColor, NS_RGB(0xDD,0xDD,0xDD));
break;
case eColor_menu:
//best guess. Menus have similar background to dialogs in most themes
res = GetMacBrushColor(kThemeBrushDialogBackgroundActive, aColor, NS_RGB(0xDD,0xDD,0xDD));
break;
case eColor_infobackground:
//Brush exists on on MacOS 9. Earlier Mac OS will use default Platinum colour
res = GetMacBrushColor(kThemeBrushNotificationWindowBackground, aColor, NS_RGB(0xFF,0xFF,0xC6));
break;
case eColor_windowframe:
//no way to fetch this colour. HARDCODING to Platinum
//res = GetMacBrushColor(??, aColor, NS_RGB(0xCC,0xCC,0xCC));
aColor = NS_RGB(0xCC,0xCC,0xCC);
res = NS_OK;
break;
case eColor_window:
res = GetMacBrushColor(kThemeBrushDocumentWindowBackground, aColor, NS_RGB(0xFF,0xFF,0xFF));
break;
case eColor__moz_field:
aColor = NS_RGB(0xff,0xff,0xff);
break;
case eColor__moz_fieldtext:
// XXX There may be a better color for this, but I'm making it
// the same as WindowText since that's what's currently used where
// I will use -moz-FieldText.
res = GetMacTextColor(kThemeTextColorDialogActive, aColor, NS_RGB(0x00,0x00,0x00));
break;
case eColor__moz_dialog:
// XXX There may be a better color for this, but I'm making it
// the same as ThreeDFace since that's what's currently used where
// I will use -moz-Dialog:
res = GetMacBrushColor(kThemeBrushButtonFaceActive, aColor, NS_RGB(0xDD,0xDD,0xDD));
break;
case eColor__moz_dialogtext:
// XXX There may be a better color for this, but I'm making it
// the same as WindowText since that's what's currently used where
// I will use -moz-DialogText.
res = GetMacTextColor(kThemeTextColorDialogActive, aColor, NS_RGB(0x00,0x00,0x00));
break;
case eColor__moz_dragtargetzone:
//default to lavender if not available
res = GetMacBrushColor(kThemeBrushDragHilite, aColor, NS_RGB(0x63,0x63,0xCE));
break;
case eColor__moz_mac_focusring:
//default to lavender if not available
res = GetMacBrushColor(kThemeBrushFocusHighlight, aColor, NS_RGB(0x63,0x63,0xCE));
break;
case eColor__moz_mac_menushadow:
res = GetMacBrushColor(kThemeBrushBevelActiveDark, aColor, NS_RGB(0x88,0x88,0x88));
break;
case eColor__moz_mac_menutextselect:
//default to white, which is what Platinum uses, if not available
res = GetMacTextColor(kThemeTextColorMenuItemSelected, aColor, NS_RGB(0xFF,0xFF,0xFF));
break;
case eColor__moz_mac_accentlightesthighlight:
//get this colour by querying variation table, ows. default to Platinum/Lavendar
res = GetMacAccentColor(eColorOffset_mac_accentlightesthighlight, aColor, NS_RGB(0xEE,0xEE,0xEE));
break;
case eColor__moz_mac_accentregularhighlight:
//get this colour by querying variation table, ows. default to Platinum/Lavendar
res = GetMacAccentColor(eColorOffset_mac_accentregularhighlight, aColor, NS_RGB(0xCC,0xCC,0xFF));
break;
case eColor__moz_mac_accentface:
//get this colour by querying variation table, ows. default to Platinum/Lavendar
res = GetMacAccentColor(eColorOffset_mac_accentface, aColor, NS_RGB(0x99,0x99,0xFF));
break;
case eColor__moz_mac_accentlightshadow:
//get this colour by querying variation table, ows. default to Platinum/Lavendar
res = GetMacAccentColor(eColorOffset_mac_accentlightshadow, aColor, NS_RGB(0x66,0x66,0xCC));
break;
case eColor__moz_mac_menuselect:
case eColor__moz_mac_accentregularshadow:
//get this colour by querying variation table, ows. default to Platinum/Lavendar
res = GetMacAccentColor(eColorOffset_mac_accentregularshadow, aColor, NS_RGB(0x63,0x63,0xCE));
break;
case eColor__moz_mac_accentdarkshadow:
//get this colour by querying variation table, ows. default to Platinum/Lavendar
res = GetMacAccentColor(eColorOffset_mac_accentdarkshadow, aColor, NS_RGB(0x00,0x00,0x88));
break;
case eColor__moz_mac_accentdarkestshadow:
//get this colour by querying variation table, ows. default to Platinum/Lavendar
res = GetMacAccentColor(eColorOffset_mac_accentdarkestshadow, aColor, NS_RGB(0x00,0x00,0x55));
break;
default:
NS_WARNING("Someone asked nsILookAndFeel for a color I don't know about");
aColor = NS_RGB(0xff,0xff,0xff);
res = NS_ERROR_FAILURE;
break;
}
return res;
}
NS_IMETHODIMP nsLookAndFeel::GetMacBrushColor( const PRInt32 aBrushType, nscolor & aColor,
const nscolor & aDefaultColor)
{
OSStatus err = noErr;
RGBColor macColor;
err = ::GetThemeBrushAsColor(aBrushType, 32, true, &macColor);
if (err == noErr)
aColor = NS_RGB(macColor.red>>8, macColor.green>>8, macColor.blue>>8);
else
aColor = aDefaultColor;
return NS_OK;
}
NS_IMETHODIMP nsLookAndFeel::GetMacTextColor(const PRInt32 aTextType, nscolor & aColor,
const nscolor & aDefaultColor)
{
OSStatus err = noErr;
RGBColor macColor;
err = ::GetThemeTextColor(aTextType, 32, true, &macColor);
if (err == noErr)
aColor = NS_RGB(macColor.red>>8, macColor.green>>8, macColor.blue>>8);
else
aColor = aDefaultColor;
return NS_OK;
}
NS_IMETHODIMP nsLookAndFeel::GetMacAccentColor( const nsMacAccentColorOffset aAccent,
nscolor & aColor,
const nscolor & aDefaultColor)
{
nsresult res = NS_OK;
OSStatus err = noErr;
ColorTable colourTable;
CTabPtr ctPointer = &colourTable;
CTabHandle ctHandle = &ctPointer;
CTabHandle *colors = &ctHandle;
RGBColor *macColor;
err = ::GetThemeAccentColors(colors);
if (err == themeHasNoAccentsErr) {
//fine, theme doesn't support accents, use default
res = NS_OK;
aColor = aDefaultColor;
} else if (err != noErr || ! colors) {
res = NS_ERROR_FAILURE;
aColor = aDefaultColor;
} else {
if ((**colors)->ctSize ==
(eColorOffset_mac_accentdarkestshadow - eColorOffset_mac_accentlightesthighlight +1)) {
//if the size is 7 then its likely to be a standard Platinum variation, so lets use it
macColor = &((**colors)->ctTable[aAccent].rgb);
aColor = NS_RGB(macColor->red>>8, macColor->green>>8, macColor->blue>>8);
res = NS_OK;
} else if ((**colors)->ctSize == -1) {
//this is probably the high contrast Black & White Platinum variation
//so lets be high contrast
res = NS_OK;
if (aAccent <= eColorOffset_mac_accentface) {
aColor = NS_RGB(0xFF,0xFF,0xFF);
} else {
aColor = NS_RGB(0x00,0x00,0x00);
}
//else if ( ?? ) // add aqua support here?
} else {
//some other size we've never heard of, no idea what to do with it
res = NS_ERROR_FAILURE;
aColor = aDefaultColor;
}
}
return res;
}
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
{
nsresult res = NS_OK;
if (mXPLookAndFeel)
{
res = mXPLookAndFeel->GetMetric(aID, aMetric);
if (NS_SUCCEEDED(res))
return res;
res = NS_OK;
}
switch (aID) {
case eMetric_WindowTitleHeight:
aMetric = 0;
break;
case eMetric_WindowBorderWidth:
aMetric = 4;
break;
case eMetric_WindowBorderHeight:
aMetric = 4;
break;
case eMetric_Widget3DBorder:
aMetric = 4;
break;
case eMetric_TextFieldHeight:
aMetric = 16;
break;
case eMetric_TextFieldBorder:
aMetric = 2;
break;
case eMetric_ButtonHorizontalInsidePaddingNavQuirks:
aMetric = 20;
break;
case eMetric_ButtonHorizontalInsidePaddingOffsetNavQuirks:
aMetric = 0;
break;
case eMetric_CheckboxSize:
aMetric = 14;
break;
case eMetric_RadioboxSize:
aMetric = 14;
break;
case eMetric_TextHorizontalInsideMinimumPadding:
aMetric = 4;
break;
case eMetric_TextVerticalInsidePadding:
aMetric = 4;
break;
case eMetric_TextShouldUseVerticalInsidePadding:
aMetric = 1;
break;
case eMetric_TextShouldUseHorizontalInsideMinimumPadding:
aMetric = 1;
break;
case eMetric_ListShouldUseHorizontalInsideMinimumPadding:
aMetric = 0;
break;
case eMetric_ListHorizontalInsideMinimumPadding:
aMetric = 4;
break;
case eMetric_ListShouldUseVerticalInsidePadding:
aMetric = 1;
break;
case eMetric_ListVerticalInsidePadding:
aMetric = 3;
break;
case eMetric_CaretBlinkTime:
aMetric = ::GetCaretTime() * 1000 / 60;
break;
case eMetric_SingleLineCaretWidth:
case eMetric_MultiLineCaretWidth:
aMetric = 1;
break;
case eMetric_ShowCaretDuringSelection:
aMetric = 0;
break;
case eMetric_SubmenuDelay:
aMetric = 200;
break;
case eMetric_MenusCanOverlapOSBar:
// xul popups are not allowed to overlap the menubar.
aMetric = 0;
break;
case eMetric_DragFullWindow:
aMetric = 1;
break;
case eMetric_ScrollArrowStyle:
ThemeScrollBarArrowStyle arrowStyle;
::GetThemeScrollBarArrowStyle ( &arrowStyle );
aMetric = arrowStyle;
break;
case eMetric_ScrollSliderStyle:
ThemeScrollBarThumbStyle thumbStyle;
::GetThemeScrollBarThumbStyle ( &thumbStyle );
aMetric = thumbStyle;
break;
default:
aMetric = 0;
res = NS_ERROR_FAILURE;
}
return res;
}
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetric)
{
nsresult res = NS_OK;
if (mXPLookAndFeel)
{
res = mXPLookAndFeel->GetMetric(aID, aMetric);
if (NS_SUCCEEDED(res))
return res;
res = NS_OK;
}
switch (aID) {
case eMetricFloat_TextFieldVerticalInsidePadding:
aMetric = 0.25f;
break;
case eMetricFloat_TextFieldHorizontalInsidePadding:
aMetric = 0.95f;
break;
case eMetricFloat_TextAreaVerticalInsidePadding:
aMetric = 0.40f;
break;
case eMetricFloat_TextAreaHorizontalInsidePadding:
aMetric = 0.40f;
break;
case eMetricFloat_ListVerticalInsidePadding:
aMetric = 0.08f;
break;
case eMetricFloat_ListHorizontalInsidePadding:
aMetric = 0.40f;
break;
case eMetricFloat_ButtonVerticalInsidePadding:
aMetric = 0.5f;
break;
case eMetricFloat_ButtonHorizontalInsidePadding:
aMetric = 0.5f;
break;
default:
aMetric = -1.0;
res = NS_ERROR_FAILURE;
}
return res;
}
#ifdef NS_DEBUG
NS_IMETHODIMP nsLookAndFeel::GetNavSize(const nsMetricNavWidgetID aWidgetID,
const nsMetricNavFontID aFontID,
const PRInt32 aFontSize,
nsSize &aSize)
{
if (mXPLookAndFeel)
{
nsresult rv = mXPLookAndFeel->GetNavSize(aWidgetID, aFontID, aFontSize, aSize);
if (NS_SUCCEEDED(rv))
return rv;
}
aSize.width = 0;
aSize.height = 0;
return NS_ERROR_NOT_IMPLEMENTED;
}
#endif

Просмотреть файл

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nsLookAndFeel
#define __nsLookAndFeel
#include "nsILookAndFeel.h"
#include "nsCOMPtr.h"
class nsLookAndFeel: public nsILookAndFeel {
NS_DECL_ISUPPORTS
public:
nsLookAndFeel();
virtual ~nsLookAndFeel();
NS_IMETHOD GetColor(const nsColorID aID, nscolor &aColor);
NS_IMETHOD GetMetric(const nsMetricID aID, PRInt32 & aMetric);
NS_IMETHOD GetMetric(const nsMetricFloatID aID, float & aMetric);
#ifdef NS_DEBUG
// This method returns the actual (or nearest estimate)
// of the Navigator size for a given form control for a given font
// and font size. This is used in NavQuirks mode to see how closely
// we match its size
NS_IMETHOD GetNavSize(const nsMetricNavWidgetID aWidgetID,
const nsMetricNavFontID aFontID,
const PRInt32 aFontSize,
nsSize &aSize);
#endif
protected:
typedef enum {
//theme accent variation colours on Mac OS,
//offsets into Platinum theme variation colour table
eColorOffset_mac_accentlightesthighlight,
eColorOffset_mac_accentregularhighlight,
eColorOffset_mac_accentface,
eColorOffset_mac_accentlightshadow,
eColorOffset_mac_accentregularshadow,
eColorOffset_mac_accentdarkshadow,
eColorOffset_mac_accentdarkestshadow
} nsMacAccentColorOffset;
nsCOMPtr<nsILookAndFeel> mXPLookAndFeel;
NS_IMETHOD GetMacBrushColor(const PRInt32 aBrushType, nscolor & aColor, const nscolor & aDefaultColor);
NS_IMETHOD GetMacTextColor(const PRInt32 aTextType, nscolor & aColor, const nscolor & aDefaultColor);
NS_IMETHOD GetMacAccentColor(const nsMacAccentColorOffset aAccent, nscolor & aColor, const nscolor & aDefaultColor);
};
#endif

Просмотреть файл

@ -0,0 +1,119 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsMacResources.h"
#include <Resources.h>
short nsMacResources::mRefNum = kResFileNotOpened;
short nsMacResources::mSaveResFile = 0;
#if !defined(XP_MACOSX)
pascal OSErr __NSInitialize(const CFragInitBlock *theInitBlock);
pascal OSErr __initializeResources(const CFragInitBlock *theInitBlock);
pascal void __NSTerminate(void);
pascal void __terminateResources(void);
//----------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------
pascal OSErr __initializeResources(const CFragInitBlock *theInitBlock)
{
OSErr err = __NSInitialize(theInitBlock);
if (err)
return err;
short saveResFile = ::CurResFile();
short refNum = FSpOpenResFile(theInitBlock->fragLocator.u.onDisk.fileSpec, fsRdPerm);
nsMacResources::SetLocalResourceFile(refNum);
::UseResFile(saveResFile);
return ::ResError();
}
//----------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------
pascal void __terminateResources(void)
{
::CloseResFile(nsMacResources::GetLocalResourceFile());
__NSTerminate();
}
#endif /*!XP_MACOSX*/
//----------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------
nsresult nsMacResources::OpenLocalResourceFile()
{
#ifdef XP_MACOSX
// XXX quick and dirty hack to make resources available so we don't crash.
if (mRefNum == kResFileNotOpened) {
FSSpec spec = { 0, 0, "\plibwidget.rsrc" };
if (FindFolder(kUserDomain, kDomainLibraryFolderType, false, &spec.vRefNum, &spec.parID) == noErr)
mRefNum = FSpOpenResFile(&spec, fsRdPerm);
}
#endif
if (mRefNum == kResFileNotOpened)
return NS_ERROR_NOT_INITIALIZED;
mSaveResFile = ::CurResFile();
::UseResFile(mRefNum);
return (::ResError() == noErr ? NS_OK : NS_ERROR_FAILURE);
}
//----------------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------------
nsresult nsMacResources::CloseLocalResourceFile()
{
if (mRefNum == kResFileNotOpened)
return NS_ERROR_NOT_INITIALIZED;
::UseResFile(mSaveResFile);
return (::ResError() == noErr ? NS_OK : NS_ERROR_FAILURE);
}

Просмотреть файл

@ -0,0 +1,59 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsMacResources_h__
#define nsMacResources_h__
#include "nsError.h"
class nsMacResources
{
public:
static nsresult OpenLocalResourceFile();
static nsresult CloseLocalResourceFile();
// you shouldn't have to use these:
static void SetLocalResourceFile(short aRefNum) {mRefNum = aRefNum;}
static short GetLocalResourceFile() {return mRefNum;}
private:
static short mRefNum;
static short mSaveResFile;
};
#endif //nsMacResources_h__

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,214 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsMenuBarX_h__
#define nsMenuBarX_h__
#include "nsIMenuBar.h"
#include "nsIMenuListener.h"
#include "nsIDocumentObserver.h"
#include "nsIChangeManager.h"
#include "nsIMenuCommandDispatcher.h"
#include "nsIPresContext.h"
#include "nsSupportsArray.h"
#include "nsVoidArray.h"
#include "nsHashtable.h"
#include "nsWeakReference.h"
#include "nsIContent.h"
#include <MacTypes.h>
#include <UnicodeConverter.h>
#include <Menus.h>
#include <CarbonEvents.h>
extern nsWeakPtr gMacMenubarX;
class nsIWidget;
class nsIDocument;
class nsIDOMNode;
namespace MenuHelpersX
{
// utility routine for getting a PresContext out of a webShell
nsresult WebShellToPresContext ( nsIWebShell* inWebShell, nsIPresContext** outContext ) ;
}
/**
* Native Mac MenuBar wrapper
*/
class nsMenuBarX : public nsIMenuBar,
public nsIMenuListener,
public nsIDocumentObserver,
public nsIChangeManager,
public nsIMenuCommandDispatcher,
public nsSupportsWeakReference
{
public:
nsMenuBarX();
virtual ~nsMenuBarX();
enum { kAppleMenuID = 1 } ;
NS_DECL_ISUPPORTS
NS_DECL_NSICHANGEMANAGER
NS_DECL_NSIMENUCOMMANDDISPATCHER
// nsIMenuListener interface
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow,
void * menuNode, void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool aMenuEvent);
// nsIDocumentObserver
NS_IMETHOD BeginUpdate(nsIDocument *aDocument);
NS_IMETHOD EndUpdate(nsIDocument *aDocument);
NS_IMETHOD BeginLoad(nsIDocument *aDocument);
NS_IMETHOD EndLoad(nsIDocument *aDocument);
NS_IMETHOD BeginReflow(nsIDocument *aDocument, nsIPresShell* aShell);
NS_IMETHOD EndReflow(nsIDocument *aDocument, nsIPresShell* aShell);
NS_IMETHOD ContentChanged(nsIDocument *aDocument,
nsIContent* aContent,
nsISupports* aSubContent);
NS_IMETHOD ContentStatesChanged(nsIDocument *aDocument,
nsIContent* aContent1,
nsIContent* aContent2);
NS_IMETHOD AttributeChanged(nsIDocument *aDocument,
nsIContent* aContent,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute,
PRInt32 aModType,
PRInt32 aHint);
NS_IMETHOD ContentAppended(nsIDocument *aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer);
NS_IMETHOD ContentInserted(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
NS_IMETHOD ContentReplaced(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer);
NS_IMETHOD ContentRemoved(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
NS_IMETHOD StyleSheetAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet);
NS_IMETHOD StyleSheetRemoved(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet);
NS_IMETHOD StyleSheetDisabledStateChanged(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
PRBool aDisabled);
NS_IMETHOD StyleRuleChanged(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule,
PRInt32 aHint);
NS_IMETHOD StyleRuleAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule);
NS_IMETHOD StyleRuleRemoved(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule);
NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument);
NS_IMETHOD Create(nsIWidget * aParent);
// nsIMenuBar Methods
NS_IMETHOD GetParent(nsIWidget *&aParent);
NS_IMETHOD SetParent(nsIWidget * aParent);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD GetMenuCount(PRUint32 &aCount);
NS_IMETHOD GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
NS_IMETHOD InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
NS_IMETHOD RemoveMenu(const PRUint32 aCount);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD Paint();
NS_IMETHOD SetNativeData(void* aData);
protected:
void GetDocument ( nsIWebShell* inWebShell, nsIDocument** outDocument ) ;
void RegisterAsDocumentObserver ( nsIWebShell* inWebShell ) ;
// Make our menubar conform to Aqua UI guidelines
void AquifyMenuBar ( ) ;
void HideItem ( nsIDOMDocument* inDoc, nsAReadableString & inID, nsIContent** outHiddenNode ) ;
OSStatus InstallCommandEventHandler ( ) ;
// command handler for some special menu items (prefs/quit/etc)
pascal static OSStatus CommandEventHandler ( EventHandlerCallRef inHandlerChain,
EventRef inEvent, void* userData ) ;
nsEventStatus ExecuteCommand ( nsIContent* inDispatchTo ) ;
// build the Apple menu shared by all menu bars.
nsresult CreateAppleMenu ( nsIMenu* inMenu ) ;
nsHashtable mObserverTable; // stores observers for content change notification
nsHashtable mCommandMapTable; // maps CommandIDs to content nodes for CarbonEvent item selection
PRUint32 mCurrentCommandID; // unique command id (per menu-bar) to give to next item that asks
PRUint32 mNumMenus;
nsSupportsArray mMenusArray; // holds refs
nsCOMPtr<nsIContent> mMenuBarContent; // menubar content node, strong ref
nsCOMPtr<nsIContent> mPrefItemContent; // on X, holds the content node for the prefs item that has
// been removed from the menubar
nsCOMPtr<nsIContent> mQuitItemContent; // as above, but for quit
nsIWidget* mParent; // weak ref
PRBool mIsMenuBarAdded;
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
nsIDocument* mDocument; // pointer to document
MenuRef mRootMenu; // root menu, representing entire menu bar.
static MenuRef sAppleMenu; // AppleMenu shared by all menubars
static EventHandlerUPP sCommandEventHandler; // carbon event handler for commands, shared
};
#endif // nsMenuBarX_h__

Просмотреть файл

@ -0,0 +1,418 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsIDocumentViewer.h"
#include "nsIContent.h"
#include "nsIPresContext.h"
#include "nsMenuBarX.h" // for MenuHelpers namespace
#include "nsMenuItemX.h"
#include "nsIMenu.h"
#include "nsIMenuBar.h"
#include "nsIWidget.h"
#include "nsIMenuListener.h"
#include "nsDynamicMDEF.h"
#include "nsINameSpaceManager.h"
#include "nsWidgetAtoms.h"
#include "nsIServiceManager.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsGUIEvent.h"
#if DEBUG
nsInstanceCounter gMenuItemCounterX("nsMenuItemX");
#endif
NS_IMPL_ISUPPORTS4(nsMenuItemX, nsIMenuItem, nsIMenuListener, nsIChangeObserver, nsISupportsWeakReference)
//
// nsMenuItemX constructor
//
nsMenuItemX::nsMenuItemX()
{
NS_INIT_REFCNT();
mMenuParent = nsnull;
mIsSeparator = PR_FALSE;
mKeyEquivalent.AssignWithConversion(" ");
mEnabled = PR_TRUE;
mIsChecked = PR_FALSE;
mMenuType = eRegular;
#if DEBUG
++gMenuItemCounterX;
#endif
}
//
// nsMenuItemX destructor
//
nsMenuItemX::~nsMenuItemX()
{
mManager->Unregister(mContent);
#if DEBUG
--gMenuItemCounterX;
#endif
}
NS_METHOD nsMenuItemX::Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator,
EMenuItemType aItemType, PRBool aEnabled,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode )
{
mContent = aNode; // addref
mMenuParent = aParent; // weak
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(aShell));
mEnabled = aEnabled;
mMenuType = aItemType;
// register for AttributeChanged messages
mManager = aManager;
nsCOMPtr<nsIChangeObserver> obs = do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this));
mManager->Register(mContent, obs); // does not addref this
mIsSeparator = aIsSeparator;
mLabel = aLabel;
return NS_OK;
}
NS_METHOD
nsMenuItemX::GetLabel(nsString &aText)
{
aText = mLabel;
return NS_OK;
}
NS_METHOD
nsMenuItemX::GetEnabled(PRBool *aIsEnabled)
{
*aIsEnabled = mEnabled;
return NS_OK;
}
NS_METHOD nsMenuItemX::SetChecked(PRBool aIsEnabled)
{
mIsChecked = aIsEnabled;
// update the content model. This will also handle unchecking our siblings
// if we are a radiomenu
mContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::checked,
mIsChecked ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"), PR_TRUE);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::GetChecked(PRBool *aIsEnabled)
{
*aIsEnabled = mIsChecked;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::GetMenuItemType(EMenuItemType *aType)
{
*aType = mMenuType;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::GetTarget(nsIWidget *& aTarget)
{
NS_IF_ADDREF(aTarget = mTarget);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::GetNativeData(void *& aData)
{
//aData = (void *)mMenu;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::AddMenuListener(nsIMenuListener * aMenuListener)
{
mXULCommandListener = aMenuListener; // addref
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::RemoveMenuListener(nsIMenuListener * aMenuListener)
{
if (mXULCommandListener.get() == aMenuListener)
mXULCommandListener = nsnull;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::IsSeparator(PRBool & aIsSep)
{
aIsSep = mIsSeparator;
return NS_OK;
}
//-------------------------------------------------------------------------
// nsIMenuListener interface
//-------------------------------------------------------------------------
nsEventStatus nsMenuItemX::MenuItemSelected(const nsMenuEvent & aMenuEvent)
{
// this is all handled by Carbon Events
return nsEventStatus_eConsumeNoDefault;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItemX::MenuSelected(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
// nsIMenuListener interface
//-------------------------------------------------------------------------
nsEventStatus nsMenuItemX::MenuDeselected(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItemX::MenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell)
{
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItemX::MenuDestruct(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItemX::CheckRebuild(PRBool & aNeedsRebuild)
{
aNeedsRebuild = PR_TRUE;
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItemX::SetRebuild(PRBool aNeedsRebuild)
{
//mNeedsRebuild = aNeedsRebuild;
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
/**
* Executes the "cached" JavaScript Command
* @return NS_OK if the command was executed properly, otherwise an error code
*/
NS_METHOD nsMenuItemX::DoCommand()
{
nsresult rv = NS_ERROR_FAILURE;
nsCOMPtr<nsIPresContext> presContext;
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
if (!webShell)
return nsEventStatus_eConsumeNoDefault;
MenuHelpersX::WebShellToPresContext(webShell, getter_AddRefs(presContext));
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_XUL_COMMAND;
// See if we have a command element. If so, we execute on the command instead
// of on our content element.
nsAutoString command;
mContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::command, command);
if (!command.IsEmpty()) {
nsCOMPtr<nsIDocument> doc;
mContent->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));
nsCOMPtr<nsIDOMElement> commandElt;
domDoc->GetElementById(command, getter_AddRefs(commandElt));
nsCOMPtr<nsIContent> commandContent(do_QueryInterface(commandElt));
if (commandContent)
commandContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
else
mContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
return nsEventStatus_eConsumeNoDefault;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::GetModifiers(PRUint8 * aModifiers)
{
nsresult res = NS_OK;
*aModifiers = mModifiers;
return res;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::SetModifiers(PRUint8 aModifiers)
{
nsresult res = NS_OK;
mModifiers = aModifiers;
return res;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::SetShortcutChar(const nsString &aText)
{
nsresult res = NS_OK;
mKeyEquivalent = aText;
return res;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItemX::GetShortcutChar(nsString &aText)
{
nsresult res = NS_OK;
aText = mKeyEquivalent;
return res;
}
//
// UncheckRadioSiblings
//
// walk the sibling list looking for nodes with the same name and
// uncheck them all.
//
void
nsMenuItemX :: UncheckRadioSiblings(nsIContent* inCheckedContent)
{
nsAutoString myGroupName;
inCheckedContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::name, myGroupName);
if ( ! myGroupName.Length() ) // no groupname, nothing to do
return;
nsCOMPtr<nsIContent> parent;
inCheckedContent->GetParent(*getter_AddRefs(parent));
if ( !parent )
return;
// loop over siblings
PRInt32 count;
parent->ChildCount(count);
for ( PRInt32 i = 0; i < count; ++i ) {
nsCOMPtr<nsIContent> sibling;
parent->ChildAt(i, *getter_AddRefs(sibling));
if ( sibling ) {
if ( sibling.get() != inCheckedContent ) { // skip this node
// if the current sibling is in the same group, clear it
nsAutoString currGroupName;
sibling->GetAttr(kNameSpaceID_None, nsWidgetAtoms::name, currGroupName);
if ( currGroupName == myGroupName )
sibling->SetAttr(kNameSpaceID_None, nsWidgetAtoms::checked, NS_LITERAL_STRING("false"), PR_TRUE);
}
}
} // for each sibling
} // UncheckRadioSiblings
#pragma mark -
//
// nsIChangeObserver
//
NS_IMETHODIMP
nsMenuItemX :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, nsIAtom *aAttribute,
PRInt32 aHint)
{
if (aAttribute == nsWidgetAtoms::checked) {
// if we're a radio menu, uncheck our sibling radio items. No need to
// do any of this if we're just a normal check menu.
if ( mMenuType == eRadio ) {
nsAutoString checked;
mContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::checked, checked);
if (checked == NS_LITERAL_STRING("true") )
UncheckRadioSiblings(mContent);
}
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
}
else if (aAttribute == nsWidgetAtoms::disabled || aAttribute == nsWidgetAtoms::hidden ||
aAttribute == nsWidgetAtoms::collapsed ) {
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
}
return NS_OK;
} // AttributeChanged
NS_IMETHODIMP
nsMenuItemX :: ContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
{
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
return NS_OK;
} // ContentRemoved
NS_IMETHODIMP
nsMenuItemX :: ContentInserted(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
{
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(mMenuParent);
listener->SetRebuild(PR_TRUE);
return NS_OK;
} // ContentInserted

Просмотреть файл

@ -0,0 +1,122 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsMenuItemX_h__
#define nsMenuItemX_h__
#include "nsIMenuItem.h"
#include "nsString.h"
#include "nsIMenuListener.h"
#include "nsIChangeManager.h"
#include "nsWeakReference.h"
#include "nsIWidget.h"
class nsIMenu;
/**
* Native Motif MenuItem wrapper
*/
class nsMenuItemX : public nsIMenuItem,
public nsIMenuListener,
public nsIChangeObserver,
public nsSupportsWeakReference
{
public:
nsMenuItemX();
virtual ~nsMenuItemX();
// nsISupports
NS_DECL_ISUPPORTS
NS_DECL_NSICHANGEOBSERVER
// nsIMenuItem Methods
NS_IMETHOD Create ( nsIMenu* aParent, const nsString & aLabel, PRBool aIsSeparator,
EMenuItemType aItemType, PRBool aEnabled,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode ) ;
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetShortcutChar(const nsString &aText);
NS_IMETHOD GetShortcutChar(nsString &aText);
NS_IMETHOD GetEnabled(PRBool *aIsEnabled);
NS_IMETHOD SetChecked(PRBool aIsEnabled);
NS_IMETHOD GetChecked(PRBool *aIsEnabled);
NS_IMETHOD GetMenuItemType(EMenuItemType *aIsCheckbox);
NS_IMETHOD GetTarget(nsIWidget *& aTarget);
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD IsSeparator(PRBool & aIsSep);
NS_IMETHOD DoCommand();
NS_IMETHOD SetModifiers(PRUint8 aModifiers);
NS_IMETHOD GetModifiers(PRUint8 * aModifiers);
// nsIMenuListener interface
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow,
void * menuNode, void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool aMenuEvent);
protected:
void UncheckRadioSiblings ( nsIContent* inCheckedElement ) ;
nsString mLabel;
nsString mKeyEquivalent;
nsIMenu* mMenuParent; // weak, parent owns us
nsIChangeManager* mManager; // weak
nsCOMPtr<nsIWidget> mTarget; // never set?
nsCOMPtr<nsIMenuListener> mXULCommandListener;
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
nsCOMPtr<nsIContent> mContent;
PRUint8 mModifiers;
PRPackedBool mIsSeparator;
PRPackedBool mEnabled;
PRPackedBool mIsChecked;
EMenuItemType mMenuType;
};
#endif // nsMenuItem_h__

1436
widget/src/cocoa/nsMenuX.cpp Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

165
widget/src/cocoa/nsMenuX.h Normal file
Просмотреть файл

@ -0,0 +1,165 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsMenuX_h__
#define nsMenuX_h__
#include "nsCOMPtr.h"
#include "nsIMenu.h"
#include "nsSupportsArray.h"
#include "nsIMenuListener.h"
#include "nsIChangeManager.h"
#include "nsWeakReference.h"
#include <Menus.h>
#include <UnicodeConverter.h>
#include <CarbonEvents.h>
class nsIMenuBar;
class nsIMenuListener;
//static PRInt16 mMacMenuIDCount; // use GetUniqueMenuID()
extern PRInt16 mMacMenuIDCount;// = kMacMenuID;
class nsMenuX : public nsIMenu,
public nsIMenuListener,
public nsIChangeObserver,
public nsSupportsWeakReference
{
public:
nsMenuX();
virtual ~nsMenuX();
NS_DECL_ISUPPORTS
NS_DECL_NSICHANGEOBSERVER
// nsIMenuListener methods
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow,
void * menuNode, void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
nsEventStatus CheckRebuild(PRBool & aMenuEvent);
nsEventStatus SetRebuild(PRBool aMenuEvent);
// nsIMenu Methods
NS_IMETHOD Create ( nsISupports * aParent, const nsAReadableString &aLabel, const nsAReadableString &aAccessKey,
nsIChangeManager* aManager, nsIWebShell* aShell, nsIContent* aNode ) ;
NS_IMETHOD GetParent(nsISupports *&aParent);
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetLabel(const nsAReadableString &aText);
NS_IMETHOD GetAccessKey(nsString &aText);
NS_IMETHOD SetAccessKey(const nsAReadableString &aText);
NS_IMETHOD AddItem(nsISupports* aText);
NS_IMETHOD AddSeparator();
NS_IMETHOD GetItemCount(PRUint32 &aCount);
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
NS_IMETHOD RemoveItem(const PRUint32 aPos);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void** aData);
NS_IMETHOD SetNativeData(void* aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD GetMenuContent(nsIContent ** aMenuNode);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
NS_IMETHOD IsHelpMenu(PRBool* aIsEnabled);
//
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
protected:
// Determines how many menus are visible among the siblings that are before me.
// It doesn't matter if I am visible.
nsresult CountVisibleBefore ( PRUint32* outVisibleBefore ) ;
// fetch the content node associated with the menupopup item
void GetMenuPopupContent ( nsIContent** aResult ) ;
// Insert a new item in this menu with index |inItemIndex| with the text |inItemLabel|,
// middle-truncated to a certain pixel width with an elipsis.
void InsertMenuItemWithTruncation ( nsAutoString & inItemLabel,
PRUint32 inItemIndex ) ;
// fire handlers for oncreate/ondestroy
PRBool OnDestroy() ;
PRBool OnCreate() ;
PRBool OnDestroyed() ;
PRBool OnCreated() ;
void LoadMenuItem ( nsIMenu* pParentMenu, nsIContent* menuitemContent );
void LoadSubMenu ( nsIMenu * pParentMenu, nsIContent* menuitemContent );
void LoadSeparator ( nsIContent* menuitemContent );
nsEventStatus HelpMenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
void* unused, void* aWebShell);
MenuHandle NSStringNewMenu(short menuID, nsString& menuTitle);
protected:
nsString mLabel;
PRUint32 mNumMenuItems;
nsSupportsArray mMenuItemsArray; // array holds refs
nsISupports* mParent; // weak, my parent owns me
nsIChangeManager* mManager; // weak ref, it will outlive us [menubar]
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
nsCOMPtr<nsIContent> mMenuContent; // the |menu| tag, strong ref
nsCOMPtr<nsIMenuListener> mListener; // strong ref
// MacSpecific
PRInt16 mMacMenuID;
MenuHandle mMacMenuHandle;
PRInt16 mHelpMenuOSItemsCount;
PRPackedBool mIsHelpMenu;
PRPackedBool mIsEnabled;
PRPackedBool mDestroyHandlerCalled;
PRPackedBool mNeedsRebuild;
PRPackedBool mConstructed;
PRPackedBool mVisible; // are we visible to the user?
EventHandlerRef mHandler; // our event handler
};
#endif // nsMenuX_h__

Просмотреть файл

@ -0,0 +1,278 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// Mike Pinkerton
// Netscape Communications
//
// See header file for details
//
#include "nsMimeMapper.h"
#include "nsITransferable.h"
#include "nsString.h"
#include "nsReadableUtils.h"
#include <Drag.h>
#include <Scrap.h>
nsMimeMapperMac :: nsMimeMapperMac ( const char* inMappings )
: mCounter(0)
{
if (inMappings && strlen(inMappings) )
ParseMappings ( inMappings );
}
nsMimeMapperMac :: ~nsMimeMapperMac ( )
{
}
//
// MapMimeTypeToMacOSType
//
// Given a mime type, map this into the appropriate MacOS clipboard type. For
// types that we don't know about intrinsicly, use a trick to get a unique 4
// character code.
//
// When a mapping is made, store it in the current mapping list so it can
// be exported along with the data.
//
ResType
nsMimeMapperMac :: MapMimeTypeToMacOSType ( const char* aMimeStr, PRBool inAddIfNotPresent )
{
ResType format = 0;
// first check if it is already in our list.
for ( MimeMapConstIterator it = mMappings.begin(); it != mMappings.end(); ++it ) {
if ( it->second.Equals(aMimeStr) ) {
format = it->first;
break;
}
}
// if it's not there, do a mapping and put it there. Some things we want to map
// to specific MacOS types, like 'TEXT'. Others are internal and we don't really
// care about what they look like, just that they have a fairly unique flavor type.
//
// Don't put standard MacOS flavor mappings into the mapping list because we'll
// pick them up by special casing MapMacsOSTypeToMimeType(). This means that
// the low two bytes of the generated flavor can be used as an index into the list.
if ( !format ) {
if ( PL_strcmp(aMimeStr, kTextMime) == 0 )
format = kScrapFlavorTypeText;
else if ( PL_strcmp(aMimeStr, kFileMime) == 0 )
format = flavorTypeHFS;
else if ( PL_strcmp(aMimeStr, kPNGImageMime) == 0 )
format = kScrapFlavorTypePicture;
else if ( PL_strcmp(aMimeStr, kJPEGImageMime) == 0 )
format = kScrapFlavorTypePicture;
else if ( PL_strcmp(aMimeStr, kGIFImageMime) == 0 )
format = kScrapFlavorTypePicture;
else if ( PL_strcmp(aMimeStr, kUnicodeMime) == 0 )
format = kScrapFlavorTypeUnicode;
else if ( inAddIfNotPresent ) {
// create the flavor based on the unique id in the lower two bytes and 'MZ' in the
// upper two bytes.
format = mCounter++;
format |= ('..MZ' << 16);
// stick it in the mapping list
mMappings.push_back ( MimePair(format, nsCAutoString(aMimeStr)) );
}
}
if ( inAddIfNotPresent )
NS_ASSERTION ( format, "Didn't map mimeType to a macOS type for some reason" );
return format;
} // MapMimeTypeToMacOSType
//
// MapMacOSTypeToMimeType
//
// Given a MacOS flavor, map this back into the Mozilla mimetype. Uses the mappings
// that have already been loaded into this class. If there aren't any, that's ok too, but
// we probably won't get a match in that case.
//
void
nsMimeMapperMac :: MapMacOSTypeToMimeType ( ResType inMacType, nsCAutoString & outMimeStr )
{
switch ( inMacType ) {
case kScrapFlavorTypeText: outMimeStr = kTextMime; break;
case kScrapFlavorTypeUnicode: outMimeStr = kUnicodeMime; break;
case flavorTypeHFS: outMimeStr = kFileMime; break;
// This flavor is the old 4.x Composer flavor for HTML. The actual data is a binary
// data structure which we do NOT want to deal with in any way shape or form. I am
// only including this flavor here so we don't accidentally use it ourselves and
// get very very confused.
case 'EHTM':
// Fall through to the unknown case.
default:
outMimeStr = "unknown";
// if the flavor starts with 'MZ' then it's probably one of our encoded ones. If not,
// we have no idea what it is. The way this was encoded means that we can use the
// lower two byts of the flavor as an index into our mapping list.
if ( inMacType & ('..MZ' << 16) ) {
unsigned short index = inMacType & 0x0000FFFF; // extract the index into our internal list
if ( index < mMappings.size() )
outMimeStr = mMappings[index].second;
else
NS_WARNING("Found a flavor starting with 'MZ..' that isn't one of ours!");
}
} // case of which flavor
} // MapMacOSTypeToMimeType
//
// ParseMappings
//
// The mappings are of the form
// 1..N of (<4 char code> <space> <mime type>).
//
// It is perfectly acceptable for there to be no mappings (either |inMappings|
// is null or an emtpy string).
//
// NOTE: we make the assumption that the data is NULL terminated.
//
void
nsMimeMapperMac :: ParseMappings ( const char* inMappings )
{
if ( !inMappings )
return;
const char* currPosition = inMappings;
while ( *currPosition ) {
char mimeType[100];
ResType flavor = nsnull;
sscanf ( currPosition, "%ld %s ", &flavor, mimeType );
mMappings.push_back( MimePair(flavor, nsCAutoString(mimeType)) );
currPosition += 10 + 2 + strlen(mimeType); // see ExportMapping() for explanation of this calculation
++mCounter;
} // while we're not at the end yet
} // ParseMappings
//
// ExportMapping
//
// The mappings are of the form
// <# of pairs> 1..N of (<4 char code> <space> <mime type> <space>)
//
// Caller is responsible for disposing of the memory allocated here. |outLength| counts
// the null at the end of the string.
//
char*
nsMimeMapperMac :: ExportMapping ( short * outLength ) const
{
NS_WARN_IF_FALSE ( outLength, "No out param provided" );
if ( outLength )
*outLength = 0;
#if 0
// I'm leaving this code in here just to prove a point. If we were allowed to
// use string stream's (we're not, because of bloat), this is all the code I'd have
// to write to do all the crap down below.
ostringstream ostr;
// for each pair, write out flavor and mime types
for ( MimeMapConstIterator it = mMappings.begin(); it != mMappings.end(); ++it ) {
const char* mimeType = ToNewCString(it->second);
ostr << it->first << ' ' << mimeType << ' ';
delete [] mimeType;
}
return ostr.str().c_str();
#endif
char* exportBuffer = nsnull;
// figure out about how long the composed string will be
short len = 0;
for ( MimeMapConstIterator it = mMappings.begin(); it != mMappings.end(); ++it ) {
len += 10; // <4 char code> (any decimal representation of 'MZXX' will be 10 digits)
len += 2; // for the two spaces
len += it->second.Length(); // <mime type>
}
// create a string of that length and fill it in with each mapping. We have to
// consider the possibility that there aren't any generic (internal mozilla) flavors
// so the map could be empty.
exportBuffer = NS_STATIC_CAST(char*, nsMemory::Alloc(len + 1)); // don't forget the NULL
if ( !exportBuffer )
return nsnull;
*exportBuffer = '\0'; // null terminate at the start for strcat()
if ( len ) {
char* posInString = exportBuffer;
for ( MimeMapConstIterator it = mMappings.begin(); it != mMappings.end(); ++it ) {
// create a buffer for this mapping, fill it in, and append it to our
// ongoing result buffer, |exportBuffer|.
char* currMapping = new char[10 + 2 + it->second.Length() + 1]; // same computation as above, plus NULL
char* mimeType = ToNewCString(it->second);
if ( currMapping && mimeType ) {
sprintf(currMapping, "%ld %s ", it->first, mimeType);
strcat(posInString, currMapping);
posInString += strlen(currMapping); // advance marker to get ready for next mapping
}
nsCRT::free ( mimeType );
nsCRT::free ( currMapping );
}
*posInString = '\0'; // null terminate our resulting string
} // if there is anything in our list
if ( outLength )
*outLength = len + 1; // don't forget the NULL
return exportBuffer;
} // ExportMapping

Просмотреть файл

@ -0,0 +1,115 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//
// Mike Pinkerton
// Netscape Communications
//
// Contains the interface for |nsMimeMapper|, which is used to map between
// mozilla defined mime types (such as text/html or mozilla/toolbaritem) and
// MacOS flavors which are 4-character codes. Since's it's not easy to go
// from N characters down to 4 and back to N without loss, we need a different
// mechanism than just some hash algorithm.
//
// The way this is generally used is to instantiate a mime mapper when you're
// about to hand data to the OS and then ask it to map the mime type into a
// 4-character code. If it's not one that the mapper knows about intrinsically,
// it creates a unique type and remembers the mapping internally. Do this for each
// different flavor of data you have. Then, when you're ready to hand the
// data to the OS for real, ask the mapper to export its mapping list (with
// ExportMapping()) which can be put into a special, well known, data flavor
// that goes into the OS along with the data.
//
// When pulling data out of the OS and into mozilla, the mapper is used to
// convert from the 4-character codes the OS knows about back to the original mime
// types. At this stage, depending the originator of the data (mozilla or some other
// mac app), you may or may not have a mapping flavor which explicitly lays out the
// conversions. If you do, load it (you have to do this yourself) and pass it to the
// ctor. If you don't, that's ok too and the well-known mappings can still be performed.
//
#ifndef nsMimeMapper_h__
#define nsMimeMapper_h__
#include <utility>
#include <vector>
#include <Types.h>
#include "nsString.h"
using std::pair;
class nsMimeMapperMac
{
public:
enum { kMappingFlavor = 'MOZm' } ;
nsMimeMapperMac ( const char* inMappings = nsnull ) ;
~nsMimeMapperMac ( ) ;
// Converts from mime type (eg: text/plain) to MacOS type (eg: 'TEXT'). If
// the mapping failed, the resulting restype will be null.
ResType MapMimeTypeToMacOSType ( const char* aMimeStr, PRBool inAddIfNotPresent = PR_TRUE ) ;
void MapMacOSTypeToMimeType ( ResType inMacType, nsCAutoString & outMimeStr ) ;
// Takes the internal mappings and converts them to a string for
// placing on the clipboard or in a drag item. |outLength| includes
// the NULL at the end of the string.
char* ExportMapping ( short * outLength ) const;
static ResType MappingFlavor ( ) { return kMappingFlavor; }
private:
void ParseMappings ( const char* inMappings ) ;
typedef pair<ResType, nsCAutoString> MimePair;
typedef std::vector<MimePair> MimeMap;
typedef MimeMap::iterator MimeMapIterator;
typedef MimeMap::const_iterator MimeMapConstIterator;
// the keeper of the data
MimeMap mMappings;
// an increasing counter for generating unique flavors
short mCounter;
// don't want people copying this until copy ctor does the right thing
nsMimeMapperMac ( const nsMimeMapperMac & ) ;
}; // nsMimeMapperMac
#endif

Просмотреть файл

@ -0,0 +1,526 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsRegionMac.h"
#include "prmem.h"
#include "nsCarbonHelpers.h"
NS_EXPORT nsNativeRegionPool sNativeRegionPool;
//------------------------------------------------------------------------
nsNativeRegionPool::nsNativeRegionPool()
{
mRegionSlots = nsnull;
mEmptySlots = nsnull;
}
//------------------------------------------------------------------------
nsNativeRegionPool::~nsNativeRegionPool()
{
// Release all of the regions.
if (mRegionSlots != nsnull) {
nsRegionSlot* slot = mRegionSlots;
while (slot != nsnull) {
::DisposeRgn(slot->mRegion);
nsRegionSlot* next = slot->mNext;
delete slot;
slot = next;
}
}
// Release all empty slots.
if (mEmptySlots != nsnull) {
nsRegionSlot* slot = mEmptySlots;
while (slot != nsnull) {
nsRegionSlot* next = slot->mNext;
delete slot;
slot = next;
}
}
}
//------------------------------------------------------------------------
RgnHandle nsNativeRegionPool::GetNewRegion()
{
nsRegionSlot* slot = mRegionSlots;
if (slot != nsnull) {
RgnHandle region = slot->mRegion;
// remove this slot from the free list.
mRegionSlots = slot->mNext;
// transfer this slot to the empty slot list for reuse.
slot->mRegion = nsnull;
slot->mNext = mEmptySlots;
mEmptySlots = slot;
// initialize the region.
::SetEmptyRgn(region);
return region;
}
// return a fresh new region. a slot will be created to hold it
// if and when the region is released.
return (::NewRgn());
}
//------------------------------------------------------------------------
void nsNativeRegionPool::ReleaseRegion(RgnHandle aRgnHandle)
{
nsRegionSlot* slot = mEmptySlots;
if (slot != nsnull)
mEmptySlots = slot->mNext;
else
slot = new nsRegionSlot;
if (slot != nsnull) {
// put this region on the region list.
slot->mRegion = aRgnHandle;
slot->mNext = mRegionSlots;
mRegionSlots = slot;
} else {
// couldn't allocate a slot, toss the region.
::DisposeRgn(aRgnHandle);
}
}
#pragma mark -
//---------------------------------------------------------------------
nsRegionMac::nsRegionMac()
{
NS_INIT_REFCNT();
mRegion = nsnull;
mRegionType = eRegionComplexity_empty;
}
//---------------------------------------------------------------------
nsRegionMac::~nsRegionMac()
{
if (mRegion != nsnull) {
sNativeRegionPool.ReleaseRegion(mRegion);
mRegion = nsnull;
}
}
NS_IMPL_ISUPPORTS1(nsRegionMac, nsIRegion)
//---------------------------------------------------------------------
nsresult nsRegionMac::Init(void)
{
if (mRegion != nsnull)
::SetEmptyRgn(mRegion);
else
mRegion = sNativeRegionPool.GetNewRegion();
if (mRegion != nsnull) {
mRegionType = eRegionComplexity_empty;
return NS_OK;
}
return NS_ERROR_OUT_OF_MEMORY;
}
//---------------------------------------------------------------------
void nsRegionMac::SetTo(const nsIRegion &aRegion)
{
nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
::CopyRgn(pRegion->mRegion, mRegion);
SetRegionType();
}
//---------------------------------------------------------------------
void nsRegionMac::SetTo(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
::SetRectRgn(mRegion, aX, aY, aX + aWidth, aY + aHeight);
SetRegionType();
}
//---------------------------------------------------------------------
void nsRegionMac::Intersect(const nsIRegion &aRegion)
{
nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
::SectRgn(mRegion, pRegion->mRegion, mRegion);
SetRegionType();
}
//---------------------------------------------------------------------
void nsRegionMac::Intersect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
RgnHandle rectRgn = sNativeRegionPool.GetNewRegion();
if (rectRgn != nsnull) {
::SetRectRgn(rectRgn, aX, aY, aX + aWidth, aY + aHeight);
::SectRgn(mRegion, rectRgn, mRegion);
sNativeRegionPool.ReleaseRegion(rectRgn);
SetRegionType();
}
}
//---------------------------------------------------------------------
void nsRegionMac::Union(const nsIRegion &aRegion)
{
nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
::UnionRgn(mRegion, pRegion->mRegion, mRegion);
SetRegionType();
}
//---------------------------------------------------------------------
void nsRegionMac::Union(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
RgnHandle rectRgn = sNativeRegionPool.GetNewRegion();
if (rectRgn != nsnull) {
::SetRectRgn(rectRgn, aX, aY, aX + aWidth, aY + aHeight);
::UnionRgn(mRegion, rectRgn, mRegion);
sNativeRegionPool.ReleaseRegion(rectRgn);
SetRegionType();
}
}
//---------------------------------------------------------------------
void nsRegionMac::Subtract(const nsIRegion &aRegion)
{
nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
::DiffRgn(mRegion, pRegion->mRegion, mRegion);
SetRegionType();
}
//---------------------------------------------------------------------
void nsRegionMac::Subtract(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
RgnHandle rectRgn = sNativeRegionPool.GetNewRegion();
if (rectRgn != nsnull) {
::SetRectRgn(rectRgn, aX, aY, aX + aWidth, aY + aHeight);
::DiffRgn(mRegion, rectRgn, mRegion);
sNativeRegionPool.ReleaseRegion(rectRgn);
SetRegionType();
}
}
//---------------------------------------------------------------------
PRBool nsRegionMac::IsEmpty(void)
{
if (mRegionType == eRegionComplexity_empty)
return PR_TRUE;
else
return PR_FALSE;
}
//---------------------------------------------------------------------
PRBool nsRegionMac::IsEqual(const nsIRegion &aRegion)
{
nsRegionMac* pRegion = (nsRegionMac*)&aRegion;
return(::EqualRgn(mRegion, pRegion->mRegion));
}
//---------------------------------------------------------------------
void nsRegionMac::GetBoundingBox(PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight)
{
Rect macRect;
::GetRegionBounds (mRegion, &macRect);
*aX = macRect.left;
*aY = macRect.top;
*aWidth = macRect.right - macRect.left;
*aHeight = macRect.bottom - macRect.top;
}
//---------------------------------------------------------------------
void nsRegionMac::Offset(PRInt32 aXOffset, PRInt32 aYOffset)
{
::OffsetRgn(mRegion, aXOffset, aYOffset);
}
//---------------------------------------------------------------------
PRBool nsRegionMac::ContainsRect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
Rect macRect;
::SetRect(&macRect, aX, aY, aX + aWidth, aY + aHeight);
return(::RectInRgn(&macRect, mRegion));
}
//---------------------------------------------------------------------
NS_IMETHODIMP nsRegionMac::GetRects(nsRegionRectSet **aRects)
{
nsRegionRectSet *rects;
NS_ASSERTION(!(nsnull == aRects), "bad ptr");
rects = *aRects;
if (nsnull == rects) {
rects = (nsRegionRectSet *)PR_Malloc(sizeof(nsRegionRectSet) + (sizeof(nsRegionRect) << 3));
if (nsnull == rects) {
*aRects = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
rects->mRectsLen = 9;
}
rects->mNumRects = 0;
rects->mArea = 0;
/* This is a minor adaptation of code written by Hugh Fisher
and published in the RegionToRectangles example in the InfoMac archives.
ported to raptor from old macfe. MMP
*/
#define EndMark 32767
#define MaxY 32767
#define StackMax 1024
typedef struct {
short size;
Rect bbox;
short data[0];
} ** Internal;
Internal region;
short width, xAdjust, y, index, x1, x2, x;
short stackStorage[1024];
short *buffer;
region = (Internal)mRegion;
/* Check for plain rectangle */
if ((**region).size == 10) {
rects->mRects[0].x = (**region).bbox.left;
rects->mRects[0].y = (**region).bbox.top;
rects->mRects[0].width = (**region).bbox.right - (**region).bbox.left;
rects->mRects[0].height = (**region).bbox.bottom - (**region).bbox.top;
rects->mNumRects = 1;
rects->mArea = rects->mRects[0].width * rects->mRects[0].height;
*aRects = rects;
return NS_OK;
}
/* Got to scale x coordinates into range 0..something */
xAdjust = (**region).bbox.left;
width = (**region).bbox.right - xAdjust;
/* Most regions will be less than 1024 pixels wide */
if (width < StackMax)
buffer = stackStorage;
else {
buffer = (short *)PR_Malloc(width * 2);
if (buffer == NULL) {
/* Truly humungous region or very low on memory.
Quietly doing nothing seems to be the
traditional Quickdraw response. */
*aRects = rects;
return NS_OK;
}
}
/* Initialise scan line list to bottom edges */
for (x = (**region).bbox.left; x < (**region).bbox.right; x++)
buffer[x - xAdjust] = MaxY;
index = 0;
/* Loop until we hit an empty scan line */
while ((**region).data[index] != EndMark) {
y = (**region).data[index];
index++;
/* Loop through horizontal runs on this line */
while ((**region).data[index] != EndMark) {
x1 = (**region).data[index];
index ++;
x2 = (**region).data[index];
index ++;
x = x1;
while (x < x2) {
if (buffer[x - xAdjust] < y) {
nsRegionRect box;
/* We have a bottom edge - how long for? */
box.x = x;
box.y = buffer[x - xAdjust];
while (x < x2 && buffer[x - xAdjust] == box.y) {
buffer[x - xAdjust] = MaxY;
x ++;
}
/* Pass to client proc */
box.width = x - box.x;
box.height = y - box.y;
if (rects->mNumRects == rects->mRectsLen) {
void *buf = PR_Realloc((void *)rects, sizeof(nsRegionRectSet) + sizeof(nsRegionRect) * (rects->mRectsLen + 7));
if (nsnull != buf) {
rects = (nsRegionRectSet *)buf;
rects->mRectsLen += 8;
}
}
if (rects->mNumRects != rects->mRectsLen) {
rects->mArea += box.width * box.height;
rects->mRects[rects->mNumRects] = box;
rects->mNumRects++;
}
} else {
/* This becomes a top edge */
buffer[x - xAdjust] = y;
x ++;
}
}
}
index ++;
}
/* Clean up after ourselves */
if (width >= StackMax)
PR_Free((void *)buffer);
#undef EndMark
#undef MaxY
#undef StackMax
*aRects = rects;
return NS_OK;
}
//---------------------------------------------------------------------
NS_IMETHODIMP nsRegionMac::FreeRects(nsRegionRectSet *aRects)
{
if (nsnull != aRects)
PR_Free((void *)aRects);
return NS_OK;
}
//---------------------------------------------------------------------
NS_IMETHODIMP nsRegionMac::GetNativeRegion(void *&aRegion) const
{
aRegion = (void *)mRegion;
return NS_OK;
}
nsresult nsRegionMac::SetNativeRegion(void *aRegion)
{
if (aRegion) {
::CopyRgn((RgnHandle)aRegion, mRegion);
SetRegionType();
} else {
Init();
}
return NS_OK;
}
//---------------------------------------------------------------------
NS_IMETHODIMP nsRegionMac::GetRegionComplexity(nsRegionComplexity &aComplexity) const
{
aComplexity = mRegionType;
return NS_OK;
}
//---------------------------------------------------------------------
void nsRegionMac::SetRegionType()
{
if (::EmptyRgn(mRegion) == PR_TRUE)
mRegionType = eRegionComplexity_empty;
else
if ( ::IsRegionRectangular(mRegion) )
mRegionType = eRegionComplexity_rect;
else
mRegionType = eRegionComplexity_complex;
}
//---------------------------------------------------------------------
void nsRegionMac::SetRegionEmpty()
{
::SetEmptyRgn(mRegion);
SetRegionType();
}
//---------------------------------------------------------------------
RgnHandle nsRegionMac::CreateRectRegion(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
RgnHandle rectRgn = sNativeRegionPool.GetNewRegion();
if (rectRgn != nsnull)
::SetRectRgn(rectRgn, aX, aY, aX + aWidth, aY + aHeight);
return rectRgn;
}

1046
widget/src/cocoa/nsSound.cpp Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nsSound_h__
#define __nsSound_h__
#include "nsISound.h"
#include "nsSupportsArray.h"
class nsIURI;
class nsIChannel;
class nsICacheSession;
class nsSound : public nsISound
{
public:
nsSound();
virtual ~nsSound();
NS_DECL_ISUPPORTS
NS_DECL_NSISOUND
nsresult AddRequest(nsISupports* aSoundRequest);
nsresult RemoveRequest(nsISupports* aSoundRequest);
nsresult GetCacheSession(nsICacheSession** outCacheSession);
nsresult GetSoundFromCache(nsIURI* inURI, nsISupports** outSound);
nsresult PutSoundInCache(nsIChannel* inChannel, PRUint32 inDataSize, nsISupports* inSound);
protected:
nsresult GetSoundResourceName(const char* inSoundName, StringPtr outResourceName);
protected:
nsSupportsArray mSoundRequests; // array of outstanding/playing sounds
};
#endif /* __nsSound_h__ */

Просмотреть файл

@ -0,0 +1,89 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Frank Yung-Fong Tang <ftang@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <Gestalt.h>
#include "nsTSMStrategy.h"
#ifdef DEBUG
//#define FORCE_USE_UNICODE_API
//#define FORCE_NOT_USE_UNICODE_API
#endif
PRBool nsTSMStrategy::gUseUnicodeForInputMethod = PR_FALSE;
PRBool nsTSMStrategy::gUseUnicodeForKeyboard = PR_FALSE;
PRBool nsTSMStrategy::gInit = PR_FALSE;
void nsTSMStrategy::Init()
{
if ( !gInit)
{
gInit = PR_TRUE;
OSErr err;
long version;
err = Gestalt(gestaltTSMgrVersion, &version);
if ((err == noErr) && (version >= gestaltTSMgr15))
{
gUseUnicodeForInputMethod = PR_TRUE;
gUseUnicodeForKeyboard = PR_TRUE;
}
#ifdef FORCE_USE_UNICODE_API
gUseUnicodeForInputMethod = PR_TRUE;
#elif defined( FORCE_NOT_USE_UNICODE_API )
gUseUnicodeForInputMethod = PR_FALSE;
#endif
// there are no way we can use unicode for keyboard, but not using
// Unicode for IME
if ( !gUseUnicodeForInputMethod)
gUseUnicodeForKeyboard = PR_FALSE;
}
}
PRBool nsTSMStrategy::UseUnicodeForInputMethod()
{
Init();
return gUseUnicodeForInputMethod;
}
PRBool nsTSMStrategy::UseUnicodeForKeyboard()
{
Init();
return gUseUnicodeForKeyboard;
}

Просмотреть файл

@ -0,0 +1,53 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1999
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Frank Yung-Fong Tang <ftang@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsTSMStrategy_h__
#define nsTSMStrategyr_h__
#include "nscore.h"
class nsTSMStrategy {
public:
PRBool UseUnicodeForInputMethod();
PRBool UseUnicodeForKeyboard();
private:
static PRBool gUseUnicodeForInputMethod;
static PRBool gUseUnicodeForKeyboard;
static PRBool gInit;
void Init();
};
#endif // nsTSMStrategy_h__

Просмотреть файл

@ -0,0 +1,402 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsToolkit.h"
#include "nsGUIEvent.h"
#include "nsWidgetAtoms.h"
#include <Gestalt.h>
#include <Appearance.h>
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsIServiceManager.h"
#include "nsGfxCIID.h"
// Class IDs...
static NS_DEFINE_CID(kEventQueueCID, NS_EVENTQUEUE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static nsMacNSPREventQueueHandler* gEventQueueHandler = nsnull;
//
// Static thread local storage index of the Toolkit
// object associated with a given thread...
//
static PRUintn gToolkitTLSIndex = 0;
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsMacNSPREventQueueHandler::nsMacNSPREventQueueHandler(): Repeater()
{
mRefCnt = 0;
mEventQueueService = do_GetService(kEventQueueServiceCID);
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsMacNSPREventQueueHandler::~nsMacNSPREventQueueHandler()
{
StopRepeating();
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
void nsMacNSPREventQueueHandler::StartPumping()
{
++mRefCnt;
NS_LOG_ADDREF(this, mRefCnt, "nsMacNSPREventQueueHandler", sizeof(*this));
StartRepeating();
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
PRBool nsMacNSPREventQueueHandler::StopPumping()
{
if (mRefCnt > 0) {
--mRefCnt;
NS_LOG_RELEASE(this, mRefCnt, "nsMacNSPREventQueueHandler");
if (mRefCnt == 0) {
StopRepeating();
return PR_TRUE;
}
}
return PR_FALSE;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
void nsMacNSPREventQueueHandler::RepeatAction(const EventRecord& inMacEvent)
{
ProcessPLEventQueue();
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
PRBool nsMacNSPREventQueueHandler::EventsArePending()
{
PRBool pendingEvents = PR_FALSE;
if (mEventQueueService)
{
nsCOMPtr<nsIEventQueue> queue;
mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
if (queue)
queue->PendingEvents(&pendingEvents);
}
return pendingEvents;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
void nsMacNSPREventQueueHandler::ProcessPLEventQueue()
{
NS_ASSERTION(mEventQueueService, "Need event queue service here");
nsCOMPtr<nsIEventQueue> queue;
mEventQueueService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
if (queue)
{
nsresult rv = queue->ProcessPendingEvents();
NS_ASSERTION(NS_SUCCEEDED(rv), "Error processing PLEvents");
}
}
#pragma mark -
NS_IMPL_THREADSAFE_ISUPPORTS1(nsToolkit, nsIToolkit);
// assume we begin as the fg app
bool nsToolkit::sInForeground = true;
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsToolkit::nsToolkit() : mInited(false)
{
NS_INIT_REFCNT();
if (gEventQueueHandler == nsnull)
gEventQueueHandler = new nsMacNSPREventQueueHandler;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsToolkit::~nsToolkit()
{
nsWidgetAtoms::ReleaseAtoms();
/* StopPumping decrements a refcount on gEventQueueHandler; a prelude toward
stopping event handling. This is not something you want to do unless you've
bloody well started event handling and incremented the refcount. That's
done in the Init method, not the constructor, and that's what mInited is about.
*/
if (mInited && gEventQueueHandler) {
if (gEventQueueHandler->StopPumping()) {
delete gEventQueueHandler;
gEventQueueHandler = nsnull;
}
}
// Remove the TLS reference to the toolkit...
PR_SetThreadPrivate(gToolkitTLSIndex, nsnull);
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsToolkit::Init(PRThread */*aThread*/)
{
if (gEventQueueHandler)
gEventQueueHandler->StartPumping();
nsWidgetAtoms::AddRefAtoms();
mInited = true;
return NS_OK;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
PRBool nsToolkit::ToolkitBusy()
{
return (gEventQueueHandler) ? gEventQueueHandler->EventsArePending() : PR_FALSE;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
bool nsToolkit::HasAppearanceManager()
{
#define APPEARANCE_MIN_VERSION 0x0110 // we require version 1.1
static bool inited = false;
static bool hasAppearanceManager = false;
if (inited)
return hasAppearanceManager;
inited = true;
SInt32 result;
if (::Gestalt(gestaltAppearanceAttr, &result) != noErr)
return false; // no Appearance Mgr
if (::Gestalt(gestaltAppearanceVersion, &result) != noErr)
return false; // still version 1.0
hasAppearanceManager = (result >= APPEARANCE_MIN_VERSION);
return hasAppearanceManager;
}
void
nsToolkit :: AppInForeground ( )
{
sInForeground = true;
}
void
nsToolkit :: AppInBackground ( )
{
sInForeground = false;
}
bool
nsToolkit :: IsAppInForeground ( )
{
return sInForeground;
}
//-------------------------------------------------------------------------
//
// Return the nsIToolkit for the current thread. If a toolkit does not
// yet exist, then one will be created...
//
//-------------------------------------------------------------------------
NS_METHOD NS_GetCurrentToolkit(nsIToolkit* *aResult)
{
nsIToolkit* toolkit = nsnull;
nsresult rv = NS_OK;
PRStatus status;
// Create the TLS index the first time through...
if (0 == gToolkitTLSIndex) {
status = PR_NewThreadPrivateIndex(&gToolkitTLSIndex, NULL);
if (PR_FAILURE == status) {
rv = NS_ERROR_FAILURE;
}
}
if (NS_SUCCEEDED(rv)) {
toolkit = (nsIToolkit*)PR_GetThreadPrivate(gToolkitTLSIndex);
//
// Create a new toolkit for this thread...
//
if (!toolkit) {
toolkit = new nsToolkit();
if (!toolkit) {
rv = NS_ERROR_OUT_OF_MEMORY;
} else {
NS_ADDREF(toolkit);
toolkit->Init(PR_GetCurrentThread());
//
// The reference stored in the TLS is weak. It is removed in the
// nsToolkit destructor...
//
PR_SetThreadPrivate(gToolkitTLSIndex, (void*)toolkit);
}
} else {
NS_ADDREF(toolkit);
}
*aResult = toolkit;
}
return rv;
}
#pragma mark -
Handle nsMacMemoryCushion::sMemoryReserve;
nsMacMemoryCushion::nsMacMemoryCushion()
: mBufferHandle(nsnull)
{
}
nsMacMemoryCushion::~nsMacMemoryCushion()
{
::SetGrowZone(nsnull);
if (sMemoryReserve)
::DisposeHandle(sMemoryReserve);
if (mBufferHandle)
::DisposeHandle(mBufferHandle);
}
OSErr nsMacMemoryCushion::Init(Size bufferSize, Size reserveSize)
{
sMemoryReserve = ::NewHandle(reserveSize);
if (sMemoryReserve == nsnull)
return ::MemError();
mBufferHandle = ::NewHandle(bufferSize);
if (mBufferHandle == nsnull)
return ::MemError();
// make this purgable
::HPurge(mBufferHandle);
#if !TARGET_CARBON
::SetGrowZone(NewGrowZoneProc(GrowZoneProc));
#endif
return noErr;
}
void nsMacMemoryCushion::RepeatAction(const EventRecord &aMacEvent)
{
if (!RecoverMemoryReserve(kMemoryReserveSize))
{
// NS_ASSERTION(0, "Failed to recallocate memory reserve. Flushing caches");
nsMemory::HeapMinimize(PR_TRUE);
}
}
Boolean nsMacMemoryCushion::RecoverMemoryReserve(Size reserveSize)
{
if (!sMemoryReserve) return true; // not initted yet
if (*sMemoryReserve != nsnull) return true; // everything is OK
::ReallocateHandle(sMemoryReserve, reserveSize);
if (::MemError() != noErr || !*sMemoryReserve) return false;
return true;
}
Boolean nsMacMemoryCushion::RecoverMemoryBuffer(Size bufferSize)
{
if (!mBufferHandle) return true; // not initted yet
if (*mBufferHandle != nsnull) return true; // everything is OK
::ReallocateHandle(mBufferHandle, bufferSize);
if (::MemError() != noErr || !*mBufferHandle) return false;
// make this purgable
::HPurge(mBufferHandle);
return true;
}
pascal long nsMacMemoryCushion::GrowZoneProc(Size amountNeeded)
{
long freedMem = 0;
if (sMemoryReserve && *sMemoryReserve && sMemoryReserve != ::GZSaveHnd())
{
freedMem = ::GetHandleSize(sMemoryReserve);
::EmptyHandle(sMemoryReserve);
}
return freedMem;
}

Просмотреть файл

@ -0,0 +1,172 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef TOOLKIT_H
#define TOOLKIT_H
#include "nsIToolkit.h"
#include "nsRepeater.h"
#include "nsCOMPtr.h"
#include "nsIEventQueueService.h"
/**
* The toolkit abstraction is necessary because the message pump must
* execute within the same thread that created the widget under Win32.
* We don't care about that on Mac: we have only one thread for the UI
* and maybe even for the whole application.
*
* So on the Mac, the nsToolkit used to be a unique object, created once
* at startup along with nsAppShell and passed to all the top-level
* windows and it became a convenient place to throw in everything we
* didn't know where else to put, like the NSPR event queue and
* the handling of global pointers on some special widgets (focused
* widget, widget hit, widget pointed).
*
* All this has changed: the application now usually creates one copy of
* the nsToolkit per window and the special widgets had to be moved
* to the nsMacEventHandler. Also, to avoid creating several repeaters,
* the NSPR event queue has been moved to a global object of its own:
* the nsMacNSPREventQueueHandler declared below.
*
* If by any chance we support one day several threads for the UI
* on the Mac, will have to create one instance of the NSPR
* event queue per nsToolkit.
*/
#include <MacTypes.h>
class nsToolkit : public nsIToolkit
{
public:
nsToolkit();
virtual ~nsToolkit();
NS_DECL_ISUPPORTS
NS_IMETHOD Init(PRThread *aThread);
// are there pending events on the toolkit's event queue?
PRBool ToolkitBusy();
public:
// Appearance Mgr
static bool HasAppearanceManager();
// helpers to determine if the app is in the fg or bg
static void AppInForeground ( ) ;
static void AppInBackground ( ) ;
static bool IsAppInForeground ( ) ;
protected:
bool mInited;
static bool sInForeground;
};
class nsMacNSPREventQueueHandler : public Repeater
{
public:
nsMacNSPREventQueueHandler();
virtual ~nsMacNSPREventQueueHandler();
virtual void StartPumping();
virtual PRBool StopPumping();
// Repeater interface
virtual void RepeatAction(const EventRecord& inMacEvent);
PRBool EventsArePending();
protected:
void ProcessPLEventQueue();
protected:
nsrefcnt mRefCnt;
nsCOMPtr<nsIEventQueueService> mEventQueueService;
};
// class for low memory detection and handling
class nsMacMemoryCushion : public Repeater
{
public:
enum {
kMemoryBufferSize = 64 * 1024, // 64k reserve, purgeable handle purged first
kMemoryReserveSize = 32 * 1024 // 32k memory reserve, freed by the GrowZoneProc
};
nsMacMemoryCushion();
~nsMacMemoryCushion();
OSErr Init(Size bufferSize, Size reserveSize);
void RepeatAction(const EventRecord &aMacEvent);
protected:
// reallocate the memory buffer. Returns true on success
Boolean RecoverMemoryBuffer(Size bufferSize);
// allocate or recover the memory reserve. Returns true on success
Boolean RecoverMemoryReserve(Size reserveSize);
public:
static pascal long GrowZoneProc(Size amountNeeded);
protected:
static Handle sMemoryReserve;
Handle mBufferHandle; // this is first to go
};
#endif // TOOLKIT_H

Просмотреть файл

@ -0,0 +1,171 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsWatchTask.h"
#include <LowMem.h>
#include <Appearance.h>
// our global, as soon as the gfx code fragment loads, this will setup
// the VBL task automagically.
nsWatchTask gWatchTask;
//
// GetTask
//
// A nice little getter to avoid exposing the global variable
nsWatchTask&
nsWatchTask :: GetTask ( )
{
return gWatchTask;
}
nsWatchTask :: nsWatchTask ( )
: mChecksum('mozz'), mSelf(this), mTicks(::TickCount()), mBusy(PR_FALSE), mSuspended(PR_FALSE),
mInstallSucceeded(PR_FALSE), mAnimation(0)
{
}
nsWatchTask :: ~nsWatchTask ( )
{
#if !TARGET_CARBON
if ( mInstallSucceeded )
::VRemove ( (QElemPtr)&mTask );
#endif
InitCursor();
}
//
// Start
//
// Registers the VBL task and does other various init tasks to begin
// watching for time away from the event loop. It is ok to call other
// methods on this object w/out calling Start().
//
void
nsWatchTask :: Start ( )
{
#if !TARGET_CARBON
// get the watch cursor and lock it high
CursHandle watch = ::GetCursor ( watchCursor );
if ( !watch )
return;
mWatchCursor = **watch;
// setup the task
mTask.qType = vType;
mTask.vblAddr = NewVBLProc((VBLProcPtr)DoWatchTask);
mTask.vblCount = kRepeatInterval;
mTask.vblPhase = 0;
// install it
mInstallSucceeded = ::VInstall((QElemPtr)&mTask) == noErr;
#endif
} // Start
//
// DoWatchTask
//
// Called at vertical retrace. If we haven't been to the event loop for
// |kTicksToShowWatch| ticks, animate the cursor.
//
// Note: assumes that the VBLTask, mTask, is the first member variable, so
// that we can piggy-back off the pointer to get to the rest of our data.
//
// (Do we still need the check for LMGetCrsrBusy()? It's not in carbon...)
//
pascal void
nsWatchTask :: DoWatchTask ( nsWatchTask* inSelf )
{
if ( inSelf->mChecksum == 'mozz' ) {
if ( !inSelf->mSuspended ) {
#if TARGET_CARBON
PRBool busy = inSelf->mBusy;
#else
PRBool busy = inSelf->mBusy && LMGetCrsrBusy();
#endif
if ( !busy ) {
if ( ::TickCount() - inSelf->mTicks > kTicksToShowWatch ) {
::SetCursor ( &(inSelf->mWatchCursor) );
inSelf->mBusy = PR_TRUE;
}
}
else
::SetCursor ( &(inSelf->mWatchCursor) );
// next frame in cursor animation
++inSelf->mAnimation;
}
#if !TARGET_CARBON
// reset the task to fire again
inSelf->mTask.vblCount = kRepeatInterval;
#endif
} // if valid checksum
} // DoWatchTask
//
// EventLoopReached
//
// Called every time we reach the event loop (or an event loop), this tickles
// our internal tick count to reset the time since our last visit to WNE and
// if we were busy, we're not any more.
//
void
nsWatchTask :: EventLoopReached ( )
{
// reset the cursor if we were animating it
if ( mBusy )
::InitCursor();
mBusy = PR_FALSE;
mTicks = ::TickCount();
mAnimation = 0;
}

Просмотреть файл

@ -0,0 +1,425 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dan Rosen <dr@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIFactory.h"
#include "nsISupports.h"
#include "nsWidgetsCID.h"
#include "nsToolkit.h"
#include "nsChildView.h"
#include "nsCocoaWindow.h"
#include "nsAppShellCocoa.h"
#include "nsFilePicker.h"
#if TARGET_CARBON
#include "nsMenuBarX.h"
#include "nsMenuX.h"
#include "nsMenuItemX.h"
#define nsMenuBar nsMenuBarX
#define nsMenu nsMenuX
#define nsMenuItem nsMenuItemX
#else
#include "nsMenuBar.h"
#include "nsMenu.h"
#include "nsMenuItem.h"
#endif
#include "nsClipboard.h"
#include "nsClipboardHelper.h"
#include "nsTransferable.h"
#include "nsHTMLFormatConverter.h"
#include "nsDragService.h"
#if USE_NATIVE_VERSION
# include "nsCheckButton.h"
#endif
#include "nsLookAndFeel.h"
#include "nsIComponentManager.h"
#include "nsSound.h"
#include "nsTimerMac.h"
#ifdef IBMBIDI
#include "nsBidiKeyboard.h"
#endif
#ifdef XP_MACOSX
#include "nsIGenericFactory.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerImpl)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCocoaWindow)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppShellCocoa)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuBar)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenu)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuItem)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
//NS_GENERIC_FACTORY_CONSTRUCTOR(nsFileSpecWithUIImpl)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
#ifdef IBMBIDI
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
#endif
static nsModuleComponentInfo components[] =
{
{ "Timer",
NS_TIMER_CID,
"@mozilla.org/timer;1",
nsTimerImplConstructor },
{ "nsWindow",
NS_WINDOW_CID,
"@mozilla.org/widgets/window/mac;1",
nsCocoaWindowConstructor },
{ "Popup nsWindow",
NS_POPUP_CID,
"@mozilla.org/widgets/popup/mac;1",
nsCocoaWindowConstructor },
{ "Child nsWindow",
NS_CHILD_CID,
"@mozilla.org/widgets/childwindow/mac;1",
nsChildViewConstructor },
{ "File Picker",
NS_FILEPICKER_CID,
"@mozilla.org/filepicker;1",
nsFilePickerConstructor },
{ "AppShell",
NS_APPSHELL_CID,
"@mozilla.org/widget/appshell/mac;1",
nsAppShellCocoaConstructor },
{ "Toolkit",
NS_TOOLKIT_CID,
"@mozilla.org/widget/toolkit/mac;1",
nsToolkitConstructor },
{ "Look And Feel",
NS_LOOKANDFEEL_CID,
"@mozilla.org/widget/lookandfeel/mac;1",
nsLookAndFeelConstructor },
{ "Menubar",
NS_MENUBAR_CID,
"@mozilla.org/widget/menubar/mac;1",
nsMenuBarConstructor },
{ "Menu",
NS_MENU_CID,
"@mozilla.org/widget/menu/mac;1",
nsMenuConstructor },
{ "MenuItem",
NS_MENUITEM_CID,
"@mozilla.org/widget/menuitem/mac;1",
nsMenuItemConstructor },
{ "Sound",
NS_SOUND_CID,
"@mozilla.org/sound;1",
nsSoundConstructor },
{ "Transferable",
NS_TRANSFERABLE_CID,
"@mozilla.org/widget/transferable;1",
nsTransferableConstructor },
{ "HTML Format Converter",
NS_HTMLFORMATCONVERTER_CID,
"@mozilla.org/widget/htmlformatconverter/mac;1",
nsHTMLFormatConverterConstructor },
{ "Clipboard",
NS_CLIPBOARD_CID,
"@mozilla.org/widget/clipboard;1",
nsClipboardConstructor },
{ "Clipboard Helper",
NS_CLIPBOARDHELPER_CID,
"@mozilla.org/widget/clipboardhelper;1",
nsClipboardHelperConstructor },
{ "Drag Service",
NS_DRAGSERVICE_CID,
"@mozilla.org/widget/dragservice;1",
nsDragServiceConstructor },
#ifdef IBMBIDI
{ "Gtk Bidi Keyboard",
NS_BIDIKEYBOARD_CID,
"@mozilla.org/widget/bidikeyboard;1",
nsBidiKeyboardConstructor },
#endif // IBMBIDI
};
NS_IMPL_NSGETMODULE(nsWidgetModule, components)
#else
// NOTE the following does not match MAC_STATIC actually used below in this file!
#define MACSTATIC
static NS_DEFINE_CID(kCWindow, NS_WINDOW_CID);
static NS_DEFINE_IID(kCTimer, NS_TIMER_CID);
static NS_DEFINE_CID(kCPopUp, NS_POPUP_CID);
static NS_DEFINE_CID(kCChild, NS_CHILD_CID);
static NS_DEFINE_CID(kCButton, NS_BUTTON_CID);
static NS_DEFINE_CID(kCCheckButton, NS_CHECKBUTTON_CID);
static NS_DEFINE_CID(kCFilePicker, NS_FILEPICKER_CID);
static NS_DEFINE_CID(kCHorzScrollbar, NS_HORZSCROLLBAR_CID);
static NS_DEFINE_CID(kCVertScrollbar, NS_VERTSCROLLBAR_CID);
static NS_DEFINE_CID(kCTextField, NS_TEXTFIELD_CID);
static NS_DEFINE_CID(kCAppShell, NS_APPSHELL_CID);
static NS_DEFINE_CID(kCToolkit, NS_TOOLKIT_CID);
static NS_DEFINE_CID(kCLookAndFeel, NS_LOOKANDFEEL_CID);
static NS_DEFINE_CID(kCLabel, NS_LABEL_CID);
static NS_DEFINE_CID(kCMenuBar, NS_MENUBAR_CID);
static NS_DEFINE_CID(kCMenu, NS_MENU_CID);
static NS_DEFINE_CID(kCMenuItem, NS_MENUITEM_CID);
static NS_DEFINE_CID(kCPopUpMenu, NS_POPUPMENU_CID);
// Drag and Drop/Clipboard
static NS_DEFINE_CID(kCDataFlavor, NS_DATAFLAVOR_CID);
static NS_DEFINE_CID(kCClipboard, NS_CLIPBOARD_CID);
static NS_DEFINE_CID(kCClipboardHelper, NS_CLIPBOARDHELPER_CID);
static NS_DEFINE_CID(kCTransferable, NS_TRANSFERABLE_CID);
static NS_DEFINE_CID(kCHTMLFormatConverter, NS_HTMLFORMATCONVERTER_CID);
static NS_DEFINE_CID(kCDragService, NS_DRAGSERVICE_CID);
// Sound services (just Beep for now)
static NS_DEFINE_CID(kCSound, NS_SOUND_CID);
#ifdef IBMBIDI
static NS_DEFINE_CID(kCBidiKeyboard, NS_BIDIKEYBOARD_CID);
#endif
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
class nsWidgetFactory : public nsIFactory
{
public:
NS_DECL_ISUPPORTS
// nsIFactory methods
NS_IMETHOD CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
nsWidgetFactory(const nsCID &aClass);
virtual ~nsWidgetFactory();
private:
nsCID mClassID;
};
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsWidgetFactory::nsWidgetFactory(const nsCID &aClass)
{
NS_INIT_REFCNT();
mClassID = aClass;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsWidgetFactory::~nsWidgetFactory()
{
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(nsWidgetFactory, nsIFactory)
//-------------------------------------------------------------------------
//
// ***IMPORTANT***
// On all platforms, we are assuming in places that the implementation of |nsIWidget|
// is really |nsWindow| and then calling methods specific to nsWindow to finish the job.
// This is by design and the assumption is safe because an nsIWidget can only be created through
// our Widget factory where all our widgets, including the XP widgets, inherit from nsWindow.
// A similar warning is in nsWindow.cpp.
//-------------------------------------------------------------------------
nsresult nsWidgetFactory::CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult)
{
if (aResult == NULL) {
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
if (nsnull != aOuter) {
return NS_ERROR_NO_AGGREGATION;
}
nsISupports *inst = nsnull;
if (mClassID.Equals(kCTimer)) {
inst = (nsISupports*)new nsTimerImpl();
}
else if (mClassID.Equals(kCWindow)) {
inst = (nsISupports*)(nsBaseWidget*)new nsCocoaWindow();
}
else if (mClassID.Equals(kCPopUp)) {
inst = (nsISupports*)(nsBaseWidget*)new nsCocoaWindow();
}
else if (mClassID.Equals(kCChild)) {
inst = (nsISupports*)(nsBaseWidget*)new nsChildView();
}
else if (mClassID.Equals(kCButton)) {
inst = (nsISupports*)(nsBaseWidget*)(nsWindow*)new nsButton();
}
else if (mClassID.Equals(kCFilePicker)) {
inst = (nsISupports*)(nsBaseFilePicker*)new nsFilePicker();
}
#if USE_NATIVE_VERSION
else if (mClassID.Equals(kCCheckButton)) {
inst = (nsISupports*)(nsBaseWidget*)(nsWindow*)new nsCheckButton();
}
#endif
else if (mClassID.Equals(kCHorzScrollbar)) {
inst = (nsISupports*)(nsBaseWidget*)(nsWindow*)new nsScrollbar(PR_FALSE);
}
else if (mClassID.Equals(kCVertScrollbar)) {
inst = (nsISupports*)(nsBaseWidget*)(nsWindow*)new nsScrollbar(PR_TRUE);
}
else if (mClassID.Equals(kCTextField)) {
inst = (nsISupports*)(nsBaseWidget*)(nsWindow*)new nsTextWidget();
}
else if (mClassID.Equals(kCAppShell)) {
inst = (nsISupports*)new nsAppShellCocoa();
}
else if (mClassID.Equals(kCToolkit)) {
inst = (nsISupports*)new nsToolkit();
}
else if (mClassID.Equals(kCLookAndFeel)) {
inst = (nsISupports*)new nsLookAndFeel();
}
else if (mClassID.Equals(kCLabel)) {
inst = (nsISupports*)(nsBaseWidget*)(nsWindow*)new nsLabel();
}
else if (mClassID.Equals(kCMenuBar)) {
inst = (nsISupports*)(nsIMenuBar*) new nsMenuBar();
}
else if (mClassID.Equals(kCMenu)) {
inst = (nsISupports*)(nsIMenu*) new nsMenu();
}
else if (mClassID.Equals(kCMenuItem)) {
inst = (nsISupports*)(nsIMenuItem*) new nsMenuItem();
}
else if (mClassID.Equals(kCPopUpMenu)) {
// inst = (nsISupports*)new nsPopUpMenu();
NS_NOTYETIMPLEMENTED("nsPopUpMenu");
}
else if (mClassID.Equals(kCSound)) {
inst = (nsISupports*)(nsISound*) new nsSound();
}
else if (mClassID.Equals(kCTransferable))
inst = (nsISupports*)new nsTransferable();
else if (mClassID.Equals(kCHTMLFormatConverter))
inst = (nsISupports*)new nsHTMLFormatConverter();
else if (mClassID.Equals(kCClipboard))
inst = (nsISupports*)new nsClipboard();
else if (mClassID.Equals(kCClipboardHelper))
inst = (nsISupports*)new nsClipboardHelper();
else if (mClassID.Equals(kCDragService))
inst = (nsISupports*)NS_STATIC_CAST(nsIDragService*, new nsDragService());
#ifdef IBMBIDI
else if (mClassID.Equals(kCBidiKeyboard))
inst = (nsISupports*)(nsIBidiKeyboard*) new nsBidiKeyboard();
#endif // IBMBIDI
if (inst == NULL) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(inst);
nsresult res = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return res;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
nsresult nsWidgetFactory::LockFactory(PRBool aLock)
{
// Not implemented in simplest case.
return NS_OK;
}
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// return the proper factory to the caller
#if defined(XP_MAC) && defined(MAC_STATIC)
extern "C" NS_WIDGET nsresult
NSGetFactory_WIDGET_DLL(nsISupports* serviceMgr,
const nsCID &aClass,
const char *aClassName,
const char *aContractID,
nsIFactory **aFactory)
#else
extern "C" NS_WIDGET nsresult
NSGetFactory(nsISupports* serviceMgr,
const nsCID &aClass,
const char *aClassName,
const char *aContractID,
nsIFactory **aFactory)
#endif
{
if (nsnull == aFactory) {
return NS_ERROR_NULL_POINTER;
}
*aFactory = new nsWidgetFactory(aClass);
if (nsnull == aFactory) {
return NS_ERROR_OUT_OF_MEMORY;
}
return (*aFactory)->QueryInterface(NS_GET_IID(nsIFactory), (void**)aFactory);
}
#endif