nspluginwrapper-0.9.91.5

Taken from Debian orig.tar.gz file.
This commit is contained in:
David Benjamin 2011-03-05 22:15:22 -05:00
parent 9d165ef722
commit 485815be8a
22 changed files with 3169 additions and 536 deletions

172
ChangeLog
View File

@ -1,3 +1,175 @@
2007-08-26 06:31 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-viewer.c: Nuke the window border, it's quite disturbing
to see it during resizing.
2007-08-25 23:03 Gwenole Beauchesne <gb.public@free.fr>
* ChangeLog: Generated by svn2cl.
2007-08-25 22:48 Gwenole Beauchesne <gb.public@free.fr>
* NEWS, nspluginwrapper.spec: 0.9.91.5
2007-08-25 22:46 Gwenole Beauchesne <gb.public@free.fr>
* src/npruntime.c, src/npw-viewer.c: Remove NPW_DISABLE_NPRUNTIME,
npruntime support has been working for a long time now.
Similarly, remove dummy npruntime handlers now that the common
supported NPAPI version is passed down.
2007-08-25 22:37 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-viewer.c, src/npw-wrapper.c: Pass down common NPAPI
version supported by both the browser and nspluginwrapper. We no
longer need to check for npruntime support ourselves, rely only
on the NPAPI version reported. Yes, if the browser lies we may
crash, but that's be browser's fault anyway.
2007-08-25 07:05 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-wrapper.c: Implement LONG64 NPP_New() and NPP_Destroy().
Fix NPStream functions so that it works with correct 64-bit
Konqueror versions too. i.e. check for identify stream.
2007-08-25 07:01 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-wrapper.c: Fix memory leak when we don't want the
NPP_Destroy() NPSavedData. Remove useless comment since the
feature was implemented.
2007-08-25 06:59 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-wrapper.c: Fix NPP_GetValue(NPPVformValue) and call new
g_NPN_MemAlloc().
2007-08-24 16:07 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-wrapper.c: Run-time detect broken 64-bit Konqueror
browsers and use another layer of thunks in that case.
2007-08-22 22:26 Gwenole Beauchesne <gb.public@free.fr>
* ChangeLog: Generated by svn2cl.
* NEWS, nspluginwrapper.spec: Updates.
2007-08-22 22:23 Gwenole Beauchesne <gb.public@free.fr>
* utils/xtrace.c: Add XCreateWindow() wrapper.
2007-08-22 22:20 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-rpc.c, src/npw-wrapper.c: Implement NPAPI 0.15
FORM_VALUES, i.e. support NPP_GetValue(NPPVformValue,..).
2007-08-22 21:51 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-rpc.h, src/npw-viewer.c, src/npw-wrapper.c: Implement
NPAPI 0.16 NPN_PushPopupsEnabledState() and
NPN_PopPopupsEnabledState().
2007-08-22 20:43 Gwenole Beauchesne <gb.public@free.fr>
* npapi/npapi.h, src/npw-viewer.c, src/npw-wrapper.c: Implement
NPAPI 0.17 RESPONSE_HEADERS, i.e. propagate NPStream::headers to
the plug-in if it is available (NULL otherwise). Fix NPStream
initialization for NPN_NewStream().
2007-08-22 19:23 Gwenole Beauchesne <gb.public@free.fr>
* Makefile: Fix build on Debian 4.0 'Etch' (and derivatives)
though libxpcom.so is currently not used and other distributions
were capable enough to compile it without the LSB build-env
hacks.
2007-08-21 22:12 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-viewer.c: Fix Flash Player 9 Update 3 beta plugin
support with XEMBED.
2007-08-21 05:02 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-viewer.c: Fix a (long) compiler warning.
2007-08-21 05:00 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-wrapper.c: Fix a potential buffer overflow.
2007-08-20 21:46 Gwenole Beauchesne <gb.public@free.fr>
* NEWS, configure, src/npw-config-template.h, src/npw-config.c:
Add support for 64-bit plugins and fix elf_swap_sym_32() for
st_shndx swapping (Martin Stransky).
2007-08-19 22:38 Gwenole Beauchesne <gb.public@free.fr>
* ChangeLog: Generated by svn2cl.
* Makefile: Make "make changelog" update the ChangeLog only,
without committing the result.
2007-08-19 17:30 Gwenole Beauchesne <gb.public@free.fr>
* nspluginwrapper.spec: BuildRequires: gtk2-devel everywhere
(gtk+2-devel was MDK specific).
2007-08-19 17:24 Gwenole Beauchesne <gb.public@free.fr>
* NEWS, nspluginwrapper.spec: Next release is 0.9.91.5.
2007-08-19 17:23 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-rpc.h, src/npw-viewer.c, src/npw-wrapper.c: Add
NPN_NewStream(), NPN_DestroyStream(), NPN_Write() support. Fix
NPP_Write() return value on error.
2007-08-19 09:31 Gwenole Beauchesne <gb.public@free.fr>
* npapi/npapi.h, npapi/nptypes.h, npapi/npupp.h: NPAPI updates.
2007-08-19 09:02 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-viewer.c, src/npw-wrapper.c: Rewrite protocol to pass
cached MIME info and plugin name/description strings. This now
is insensitive to possible garbage printed out during the call
to the plugin functions.
2007-08-19 08:01 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-wrapper.c: Drop initialization/destruction locks since
RPC handlers have been called from the Mozilla main loop for a
long time now (and not from a separate thread).
2007-08-19 07:44 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-viewer.c: Clean-up global NP funcs wrappers.
2007-08-19 06:45 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-viewer.c: Override NPPVpluginNeedsXEmbed at a more
natural place.
2007-08-18 23:43 Gwenole Beauchesne <gb.public@free.fr>
* src/npw-viewer.c, src/xembed.h: Fix focus problems (Debian bug
#435912).
2007-08-18 23:13 Gwenole Beauchesne <gb.public@free.fr>
* utils/xtrace.c: Add a few more functions and details.
2007-08-11 10:55 Gwenole Beauchesne <gb.public@free.fr>
* tests/test-plugins.html: Add link for Debian bug report #435912.
2007-04-04 06:27 Gwenole Beauchesne <gb.public@free.fr>
* TODO, src/npw-config.c, src/npw-viewer.sh: Improve fix for
"don't load native plugins".
2007-04-03 18:00 Gwenole Beauchesne <gb.public@free.fr>
* ChangeLog: Generated by svn2cl.
2007-04-03 17:59 Gwenole Beauchesne <gb.public@free.fr>
* lsb-build/headers/stddef.h: Fix NULL definition for C (openSUSE

View File

@ -121,6 +121,10 @@ libxpcom_RAWSRCS = libxpcom.c debug.c
libxpcom_SOURCES = $(libxpcom_RAWSRCS:%.c=$(SRC_PATH)/src/%.c)
libxpcom_OBJECTS = $(libxpcom_RAWSRCS:%.c=libxpcom-%.o)
libxpcom_CFLAGS = -fPIC
ifeq ($(biarch),yes)
libxpcom_CFLAGS += -I$(LSB_INC_DIR)
libxpcom_LDFLAGS = $(LDFLAGS_32) -L$(LSB_OBJ_DIR)
endif
npconfig_PROGRAM = npconfig
npconfig_RAWSRCS = npw-config.c
@ -282,6 +286,7 @@ localrpm: $(archivedir)$(SRCARCHIVE).bz2
changelog: ../common/authors.xml
svn_prefix=`svn info .|sed -n '/^URL *: .*\/svn\/\(.*\)$$/s//\1\//p'`; \
svn2cl --strip-prefix=$$svn_prefix --authors=../common/authors.xml || :
changelog.commit: changelog
svn commit -m "Generated by svn2cl." ChangeLog
$(npwrapper_LIBRARY): $(npwrapper_OBJECTS)

10
NEWS
View File

@ -1,6 +1,14 @@
nspluginwrapper NEWS -- history of user-visible changes. 2007-04-03
nspluginwrapper NEWS -- history of user-visible changes. 2007-08-26
Copyright (C) 2005-2007 Gwenole Beauchesne
Version 0.9.91.5 (BETA) - 26.Aug.2007
* Fix a memory leak in NPP_Destroy()
* Fix DiamondX XEmbed example plugin
* Fix focus problems (Debian bug #435912)
* Add support for 64-bit plugins (Martin Stransky)
* Add support for newer NPAPI 0.17 functions and variables
* Add support for broken 64-bit Konqueror versions (run-time detect)
Version 0.9.91.4 (BETA) - 03.Apr.2007
* Don't try to wrap native plugins
* Fix build on NetBSD (David Brownlee)

5
TODO
View File

@ -1,3 +1,8 @@
- Fix "don't try to load native plugins"
* This currently works because we don't ship with native viewers
* Otherwise, the plugin OS,ARCH characterisation through ELF headers only
works for Linux / FreeBSD where they have dedicated tags
=> This was only useful for Linux/i386 platforms anyway ATM
- Clean-ups
* Re-indent -gnu -br -brs
* Better split for RPC / NAPI level routines

4
configure vendored
View File

@ -647,6 +647,10 @@ if test "$target_cpu" = "i386" ; then
echo "TARGET_ARCH=i386" >> $config_mak
echo "#define TARGET_ARCH \"i386\"" >> $config_h
echo "#define TARGET_I386 1" >> $config_h
elif test "$target_cpu" = "x86_64" ; then
echo "TARGET_ARCH=x86_64" >> $config_mak
echo "#define TARGET_ARCH \"x86_64\"" >> $config_h
echo "#define TARGET_X86_64 1" >> $config_h
elif test "$target_cpu" = "ppc" ; then
echo "TARGET_ARCH=ppc" >> $config_mak
echo "#define TARGET_ARCH \"ppc\"" >> $config_h

View File

@ -126,7 +126,7 @@
/*----------------------------------------------------------------------*/
#define NP_VERSION_MAJOR 0
#define NP_VERSION_MINOR 14
#define NP_VERSION_MINOR 17
/* The OS/2 version of Netscape uses RC_DATA to define the
@ -256,6 +256,16 @@ typedef struct _NPStream
uint32 end;
uint32 lastmodified;
void* notifyData;
const char* headers; /* Response headers from host.
* Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
* Used for HTTP only; NULL for non-HTTP.
* Available from NPP_NewStream onwards.
* Plugin should copy this data before storing it.
* Includes HTTP status line and all headers,
* preferably verbatim as received from server,
* headers formatted as in HTTP ("Header: Value"),
* and newlines (\n, NOT \r\n) separating lines.
* Terminated by \n\0 (NOT \n\n\0). */
} NPStream;
@ -385,13 +395,24 @@ typedef enum {
NPPVpluginScriptableInstance = (10 | NP_ABI_MASK),
NPPVpluginScriptableIID = 11,
/* 12 and over are available on Mozilla builds starting with 0.9.9 */
/* Introduced in Mozilla 0.9.9 */
NPPVjavascriptPushCallerBool = 12,
NPPVpluginKeepLibraryInMemory = 13, /* available in Mozilla 1.0 */
/* Introduced in Mozilla 1.0 */
NPPVpluginKeepLibraryInMemory = 13,
NPPVpluginNeedsXEmbed = 14,
/* Get the NPObject for scripting the plugin. */
NPPVpluginScriptableNPObject = 15
/* Get the NPObject for scripting the plugin. Introduced in Firefox
* 1.0 (NPAPI minor version 14).
*/
NPPVpluginScriptableNPObject = 15,
/* Get the plugin value (as \0-terminated UTF-8 string data) for
* form submission if the plugin is part of a form. Use
* NPN_MemAlloc() to allocate memory for the string data. Introduced
* in Mozilla 1.8b2 (NPAPI minor version 15).
*/
NPPVformValue = 16
} NPPVariable;
/*
@ -604,13 +625,17 @@ enum NPEventType {
/*
* Version feature information
*/
#define NPVERS_HAS_STREAMOUTPUT 8
#define NPVERS_HAS_NOTIFICATION 9
#define NPVERS_HAS_LIVECONNECT 9
#define NPVERS_WIN16_HAS_LIVECONNECT 9
#define NPVERS_68K_HAS_LIVECONNECT 11
#define NPVERS_HAS_WINDOWLESS 11
#define NPVERS_HAS_XPCONNECT_SCRIPTING 13
#define NPVERS_HAS_STREAMOUTPUT 8
#define NPVERS_HAS_NOTIFICATION 9
#define NPVERS_HAS_LIVECONNECT 9
#define NPVERS_WIN16_HAS_LIVECONNECT 9
#define NPVERS_68K_HAS_LIVECONNECT 11
#define NPVERS_HAS_WINDOWLESS 11
#define NPVERS_HAS_XPCONNECT_SCRIPTING 13
#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14
#define NPVERS_HAS_FORM_VALUES 15
#define NPVERS_HAS_POPUPS_ENABLED_STATE 16
#define NPVERS_HAS_RESPONSE_HEADERS 17
/*----------------------------------------------------------------------*/
/* Function Prototypes */
@ -663,9 +688,6 @@ void NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
jref NP_LOADDS NPP_GetJavaClass(void);
#endif
NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value);
/*
* Uh, shouldn't NPP_SetValue() take an NPPVariable and not an NPNVariable?
*/
NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value);
/*
@ -704,6 +726,8 @@ NPError NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable, void *value);
void NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
void NP_LOADDS NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion);
void NP_LOADDS NPN_ForceRedraw(NPP instance);
void NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
void NP_LOADDS NPN_PopPopupsEnabledState(NPP instance);
#ifdef __cplusplus
} /* end extern "C" */

View File

@ -48,7 +48,7 @@
*/
typedef int int32_t;
typedef unsigned int uint32_t;
#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX)
#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX)
/*
* AIX and SunOS ship a inttypes.h header that defines [u]int32_t,
* but not bool for C.
@ -67,19 +67,15 @@
/*
* BSD/OS ships no header that defines uint32_t, nor bool (for C)
* OpenBSD ships no header that defines uint32_t, but provides bool as a
* macro.
* OpenBSD ships no header that defines uint32_t and using its bool macro is
* unsafe.
*/
#if defined(bsdi) || defined(OPENBSD)
typedef u_int32_t uint32_t;
#if defined(bsdi)
#if !defined(__cplusplus)
typedef int bool;
#endif
#else /* OPENBSD is defined, so use its bool */
#include <stdbool.h>
#endif
#else
/*
* FreeBSD defines uint32_t and bool.

View File

@ -1586,6 +1586,58 @@ typedef void (* NP_LOADDS NPN_SetExceptionUPP)(NPObject *obj, const NPUTF8 *mess
#endif
/* NPN_PushPopupsEnabledStateUPP */
#if _NPUPP_USE_UPP_
typedef UniversalProcPtr NPN_PushPopupsEnabledStateUPP;
enum {
uppNPN_PushPopupsEnabledStateProcInfo = kThinkCStackBased
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP)))
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPBool)))
| RESULT_SIZE(SIZE_CODE(0))
};
#define NewNPN_PushPopupsEnabledStateProc(FUNC) \
(NPN_PushPopupsEnabledStateUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PushPopupsEnabledStateProcInfo, GetCurrentArchitecture())
#define CallNPN_PushPopupsEnabledStateProc(FUNC, ARG1, ARG2) \
(jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PushPopupsEnabledStateProcInfo, (ARG1), (ARG2))
#else
typedef bool (* NP_LOADDS NPN_PushPopupsEnabledStateUPP)(NPP npp, NPBool enabled);
#define NewNPN_PushPopupsEnabledStateProc(FUNC) \
((NPN_PushPopupsEnabledStateUPP) (FUNC))
#define CallNPN_PushPopupsEnabledStateProc(FUNC, ARG1, ARG2) \
(*(FUNC))((ARG1), (ARG2))
#endif
/* NPN_PopPopupsEnabledState */
#if _NPUPP_USE_UPP_
typedef UniversalProcPtr NPN_PopPopupsEnabledStateUPP;
enum {
uppNPN_PopPopupsEnabledStateProcInfo = kThinkCStackBased
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP)))
| RESULT_SIZE(SIZE_CODE(0))
};
#define NewNPN_PopPopupsEnabledStateProc(FUNC) \
(NPN_PopPopupsEnabledStateUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PopPopupsEnabledStateProcInfo, GetCurrentArchitecture())
#define CallNPN_PopPopupsEnabledStateProc(FUNC, ARG1) \
(jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PopPopupsEnabledStateProcInfo, (ARG1))
#else
typedef bool (* NP_LOADDS NPN_PopPopupsEnabledStateUPP)(NPP npp);
#define NewNPN_PopPopupsEnabledStateProc(FUNC) \
((NPN_PopPopupsEnabledStateUPP) (FUNC))
#define CallNPN_PopPopupsEnabledStateProc(FUNC, ARG1) \
(*(FUNC))((ARG1))
#endif
@ -1661,6 +1713,8 @@ typedef struct _NPNetscapeFuncs {
NPN_HasMethodUPP hasmethod;
NPN_ReleaseVariantValueUPP releasevariantvalue;
NPN_SetExceptionUPP setexception;
NPN_PushPopupsEnabledStateUPP pushpopupsenabledstate;
NPN_PopPopupsEnabledStateUPP poppopupsenabledstate;
} NPNetscapeFuncs;
#ifdef XP_MAC

View File

@ -1,7 +1,7 @@
%define name nspluginwrapper
%define version 0.9.91.4
%define version 0.9.91.5
%define release 1
#define svndate 20070403
#define svndate 20070826
# define 32-bit arch of multiarch platforms
%define arch_32 %{nil}
@ -53,7 +53,7 @@ Source0: %{name}-%{version}%{?svndate:-%{svndate}}.tar.bz2
License: GPL
Group: Networking/WWW
Url: http://gwenole.beauchesne.info/projects/nspluginwrapper/
BuildRequires: gtk+2-devel
BuildRequires: gtk2-devel
Provides: %{name}-%{_arch} = %{version}-%{release}
Requires: %{name}-%{target_arch} = %{version}-%{release}
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
@ -158,6 +158,14 @@ fi
%endif
%changelog
* Sun Aug 26 2007 Gwenole Beauchesne <gb.public@free.fr> 0.9.91.5-1
- fix a memory leak in NPP_Destroy()
- fix DiamondX XEmbed example plugin
- fix focus problems (debian bug #435912)
- add support for 64-bit plugins (Martin Stransky)
- add support for newer NPAPI 0.17 functions and variables
- add support for broken 64-bit Konqueror versions (run-time detect)
* Mon Apr 2 2007 Gwenole Beauchesne <gb.public@free.fr> 0.9.91.4-1
- use anonymous sockets by default
- don't try to wrap native plugins

753
src/gtk2xtbin.c Normal file
View File

@ -0,0 +1,753 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim:expandtab:shiftwidth=2:tabstop=2: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* 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 Gtk2XtBin Widget Implementation.
*
* The Initial Developer of the Original Code is
* Sun Microsystems, Inc.
* Portions created by the Initial Developer are Copyright (C) 2002
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* The GtkXtBin widget allows for Xt toolkit code to be used
* inside a GTK application.
*/
#include "sysdeps.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <gdk/gdkx.h>
#include "xembed.h"
#include "gtk2xtbin.h"
/* Xlib/Xt stuff */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Shell.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
/* uncomment this if you want debugging information about widget
creation and destruction */
#define DEBUG_XTBIN 1
static void gtk_xtbin_class_init (GtkXtBinClass *klass);
static void gtk_xtbin_init (GtkXtBin *xtbin);
static void gtk_xtbin_realize (GtkWidget *widget);
static void gtk_xtbin_unrealize (GtkWidget *widget);
static void gtk_xtbin_destroy (GtkObject *object);
static void gtk_xtbin_shutdown (GtkObject *object);
/* Xt aware XEmbed */
static void xt_client_init (XtClient * xtclient,
Display *xtdisplay,
Visual *xtvisual,
Colormap xtcolormap,
int xtdepth);
static void xt_client_create (XtClient * xtclient,
Window embeder,
int height,
int width );
static void xt_client_unrealize (XtClient* xtclient);
static void xt_client_destroy (XtClient* xtclient);
static void xt_client_set_info (Widget xtplug,
unsigned long flags);
static void xt_client_event_handler (Widget w,
XtPointer client_data,
XEvent *event);
static void xt_client_handle_xembed_message (Widget w,
XtPointer client_data,
XEvent *event);
static void xt_client_focus_listener (Widget w,
XtPointer user_data,
XEvent *event);
static void xt_add_focus_listener( Widget w, XtPointer user_data );
static void xt_add_focus_listener_tree ( Widget treeroot, XtPointer user_data);
static void xt_remove_focus_listener(Widget w, XtPointer user_data);
static void send_xembed_message (XtClient *xtclient,
long message,
long detail,
long data1,
long data2,
long time);
static int error_handler (Display *display,
XErrorEvent *error);
/* For error trap of XEmbed */
static void trap_errors(void);
static int untrap_errors(void);
static int (*old_error_handler) (Display *, XErrorEvent *);
static int trapped_error_code = 0;
static GtkWidgetClass *parent_class = NULL;
GtkType
gtk_xtbin_get_type (void)
{
static GtkType xtbin_type = 0;
if (!xtbin_type) {
static const GtkTypeInfo xtbin_info =
{
"GtkXtBin",
sizeof (GtkXtBin),
sizeof (GtkXtBinClass),
(GtkClassInitFunc) gtk_xtbin_class_init,
(GtkObjectInitFunc) gtk_xtbin_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL
};
xtbin_type = gtk_type_unique (GTK_TYPE_SOCKET, &xtbin_info);
}
return xtbin_type;
}
static void
gtk_xtbin_class_init (GtkXtBinClass *klass)
{
GtkWidgetClass *widget_class;
GtkObjectClass *object_class;
parent_class = gtk_type_class (GTK_TYPE_SOCKET);
widget_class = GTK_WIDGET_CLASS (klass);
widget_class->realize = gtk_xtbin_realize;
widget_class->unrealize = gtk_xtbin_unrealize;
object_class = GTK_OBJECT_CLASS (klass);
object_class->destroy = gtk_xtbin_destroy;
}
static void
gtk_xtbin_init (GtkXtBin *xtbin)
{
xtbin->xtdisplay = NULL;
xtbin->parent_window = NULL;
xtbin->xtwindow = 0;
xtbin->x = 0;
xtbin->y = 0;
}
static void
gtk_xtbin_realize (GtkWidget *widget)
{
GtkXtBin *xtbin;
GtkAllocation allocation = { 0, 0, 200, 200 };
gint x, y, w, h, d; /* geometry of window */
#ifdef DEBUG_XTBIN
printf("gtk_xtbin_realize()\n");
#endif
g_return_if_fail (GTK_IS_XTBIN (widget));
xtbin = GTK_XTBIN (widget);
/* caculate the allocation before realize */
gdk_window_get_geometry(xtbin->parent_window, &x, &y, &w, &h, &d);
allocation.width = w;
allocation.height = h;
gtk_widget_size_allocate (widget, &allocation);
#ifdef DEBUG_XTBIN
printf("initial allocation %d %d %d %d\n", x, y, w, h);
#endif
xtbin->width = widget->allocation.width;
xtbin->height = widget->allocation.height;
/* use GtkSocket's realize */
(*GTK_WIDGET_CLASS(parent_class)->realize)(widget);
/* create the Xt client widget */
xt_client_create(&(xtbin->xtclient),
gtk_socket_get_id(GTK_SOCKET(xtbin)),
xtbin->height,
xtbin->width);
xtbin->xtwindow = XtWindow(xtbin->xtclient.child_widget);
gdk_flush();
/* now that we have created the xt client, add it to the socket. */
gtk_socket_add_id(GTK_SOCKET(widget), xtbin->xtwindow);
}
GtkWidget*
gtk_xtbin_new (GdkWindow *parent_window,
Display *xtdisplay,
Visual *xtvisual,
Colormap xtcolormap,
int xtdepth)
{
GtkXtBin *xtbin;
gpointer user_data;
assert(parent_window != NULL);
xtbin = gtk_type_new (GTK_TYPE_XTBIN);
if (!xtbin)
return (GtkWidget*)NULL;
/* Initialize the Xt toolkit */
xtbin->parent_window = parent_window;
xt_client_init(&(xtbin->xtclient), xtdisplay, xtvisual, xtcolormap, xtdepth);
/* Build the hierachy */
assert(xtbin->xtclient.xtdisplay != NULL);
xtbin->xtdisplay = xtbin->xtclient.xtdisplay;
gtk_widget_set_parent_window(GTK_WIDGET(xtbin), parent_window);
gdk_window_get_user_data(xtbin->parent_window, &user_data);
if (user_data)
gtk_container_add(GTK_CONTAINER(user_data), GTK_WIDGET(xtbin));
return GTK_WIDGET (xtbin);
}
void
gtk_xtbin_set_position (GtkXtBin *xtbin,
gint x,
gint y)
{
xtbin->x = x;
xtbin->y = y;
if (GTK_WIDGET_REALIZED (xtbin))
gdk_window_move (GTK_WIDGET (xtbin)->window, x, y);
}
void
gtk_xtbin_resize (GtkWidget *widget,
gint width,
gint height)
{
Arg args[2];
GtkXtBin *xtbin = GTK_XTBIN (widget);
GtkAllocation allocation;
#ifdef DEBUG_XTBIN
printf("gtk_xtbin_resize %p %d %d\n", (void *)widget, width, height);
#endif
XtSetArg(args[0], XtNheight, height);
XtSetArg(args[1], XtNwidth, width);
XtSetValues(xtbin->xtclient.top_widget, args, 2);
xtbin->height = height;
xtbin->width = width;
/* we need to send a size allocate so the socket knows about the
size changes */
allocation.x = xtbin->x;
allocation.y = xtbin->y;
allocation.width = xtbin->width;
allocation.height = xtbin->height;
gtk_widget_size_allocate(widget, &allocation);
}
static void
gtk_xtbin_unrealize (GtkWidget *object)
{
GtkXtBin *xtbin;
GtkWidget *widget;
#ifdef DEBUG_XTBIN
printf("gtk_xtbin_unrealize()\n");
#endif
/* gtk_object_destroy() will already hold a refcount on object
*/
xtbin = GTK_XTBIN(object);
widget = GTK_WIDGET(object);
GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
if (GTK_WIDGET_REALIZED (widget)) {
xt_client_unrealize(&(xtbin->xtclient));
}
(*GTK_WIDGET_CLASS (parent_class)->unrealize)(widget);
}
static void
gtk_xtbin_destroy (GtkObject *object)
{
GtkXtBin *xtbin;
#ifdef DEBUG_XTBIN
printf("gtk_xtbin_destroy()\n");
#endif
g_return_if_fail (object != NULL);
g_return_if_fail (GTK_IS_XTBIN (object));
xtbin = GTK_XTBIN (object);
if(xtbin->xtwindow) {
/* remove the event handler */
xt_client_destroy(&(xtbin->xtclient));
xtbin->xtwindow = 0;
}
GTK_OBJECT_CLASS(parent_class)->destroy(object);
}
/*
* Following is the implementation of Xt XEmbedded for client side
*/
/* Initial Xt plugin */
static void
xt_client_init( XtClient * xtclient,
Display *xtdisplay,
Visual *xtvisual,
Colormap xtcolormap,
int xtdepth)
{
xtclient->top_widget = NULL;
xtclient->child_widget = NULL;
xtclient->xtdisplay = xtdisplay;
xtclient->xtvisual = xtvisual;
xtclient->xtcolormap = xtcolormap;
xtclient->xtdepth = xtdepth;
}
/* Create the Xt client widgets
* */
static void
xt_client_create ( XtClient* xtclient ,
Window embedderid,
int height,
int width )
{
int n;
Arg args[6];
Widget child_widget;
Widget top_widget;
#ifdef DEBUG_XTBIN
printf("xt_client_create() \n");
#endif
String app_name, app_class;
XtGetApplicationNameAndClass(xtclient->xtdisplay, &app_name, &app_class);
top_widget = XtAppCreateShell("drawingArea", app_class,
applicationShellWidgetClass,
xtclient->xtdisplay,
NULL, 0);
xtclient->top_widget = top_widget;
/* set size of Xt window */
n = 0;
XtSetArg(args[n], XtNheight, height);n++;
XtSetArg(args[n], XtNwidth, width);n++;
XtSetValues(top_widget, args, n);
child_widget = XtVaCreateWidget("form",
compositeWidgetClass,
top_widget, NULL);
n = 0;
XtSetArg(args[n], XtNheight, height);n++;
XtSetArg(args[n], XtNwidth, width);n++;
XtSetArg(args[n], XtNvisual, xtclient->xtvisual ); n++;
XtSetArg(args[n], XtNdepth, xtclient->xtdepth ); n++;
XtSetArg(args[n], XtNcolormap, xtclient->xtcolormap ); n++;
XtSetArg(args[n], XtNborderWidth, 0); n++;
XtSetValues(child_widget, args, n);
XSync(xtclient->xtdisplay, FALSE);
xtclient->oldwindow = top_widget->core.window;
top_widget->core.window = embedderid;
/* this little trick seems to finish initializing the widget */
#if XlibSpecificationRelease >= 6
XtRegisterDrawable(xtclient->xtdisplay,
embedderid,
top_widget);
#else
_XtRegisterWindow( embedderid,
top_widget);
#endif
XtRealizeWidget(child_widget);
/* listen to all Xt events */
XSelectInput(xtclient->xtdisplay,
XtWindow(top_widget),
0x0FFFFF);
xt_client_set_info (child_widget, 0);
XtManageChild(child_widget);
xtclient->child_widget = child_widget;
/* set the event handler */
#if 0
XtAddEventHandler(child_widget,
0x0FFFFF & ~ResizeRedirectMask,
TRUE,
(XtEventHandler)xt_client_event_handler, xtclient);
XtAddEventHandler(child_widget,
SubstructureNotifyMask | ButtonReleaseMask,
TRUE,
(XtEventHandler)xt_client_focus_listener,
xtclient);
#else
XtAddEventHandler(child_widget,
(SubstructureNotifyMask | ButtonReleaseMask),
TRUE,
(XtEventHandler)xt_client_event_handler, xtclient);
#endif
XSync(xtclient->xtdisplay, FALSE);
}
static void
xt_client_unrealize ( XtClient* xtclient )
{
#if XlibSpecificationRelease >= 6
XtUnregisterDrawable(xtclient->xtdisplay,
xtclient->top_widget->core.window);
#else
_XtUnregisterWindow(xtclient->top_widget->core.window,
xtclient->top_widget);
#endif
/* flush the queue before we returning origin top_widget->core.window
or we can get X error since the window is gone */
XSync(xtclient->xtdisplay, False);
xtclient->top_widget->core.window = xtclient->oldwindow;
XtUnrealizeWidget(xtclient->top_widget);
}
static void
xt_client_destroy (XtClient* xtclient)
{
if(xtclient->top_widget) {
XtRemoveEventHandler(xtclient->child_widget, 0x0FFFFF, TRUE,
(XtEventHandler)xt_client_event_handler, xtclient);
XtDestroyWidget(xtclient->top_widget);
xtclient->top_widget = NULL;
}
}
static void
xt_client_set_info (Widget xtplug, unsigned long flags)
{
unsigned long buffer[2];
Atom infoAtom = XInternAtom(XtDisplay(xtplug), "_XEMBED_INFO", False);
buffer[1] = 0; /* Protocol version */
buffer[1] = flags;
XChangeProperty (XtDisplay(xtplug), XtWindow(xtplug),
infoAtom, infoAtom, 32,
PropModeReplace,
(unsigned char *)buffer, 2);
}
static void
xt_client_handle_xembed_message(Widget w, XtPointer client_data, XEvent *event)
{
XtClient *xtplug = (XtClient*)client_data;
switch (event->xclient.data.l[1])
{
case XEMBED_EMBEDDED_NOTIFY:
break;
case XEMBED_WINDOW_ACTIVATE:
#ifdef DEBUG_XTBIN
printf("Xt client get XEMBED_WINDOW_ACTIVATE\n");
#endif
break;
case XEMBED_WINDOW_DEACTIVATE:
#ifdef DEBUG_XTBIN
printf("Xt client get XEMBED_WINDOW_DEACTIVATE\n");
#endif
break;
case XEMBED_MODALITY_ON:
#ifdef DEBUG_XTBIN
printf("Xt client get XEMBED_MODALITY_ON\n");
#endif
break;
case XEMBED_MODALITY_OFF:
#ifdef DEBUG_XTBIN
printf("Xt client get XEMBED_MODALITY_OFF\n");
#endif
break;
case XEMBED_FOCUS_IN:
case XEMBED_FOCUS_OUT:
{
XEvent xevent;
memset(&xevent, 0, sizeof(xevent));
if(event->xclient.data.l[1] == XEMBED_FOCUS_IN) {
#ifdef DEBUG_XTBIN
printf("XTEMBED got focus in\n");
#endif
xevent.xfocus.type = FocusIn;
}
else {
#ifdef DEBUG_XTBIN
printf("XTEMBED got focus out\n");
#endif
xevent.xfocus.type = FocusOut;
}
xevent.xfocus.window = XtWindow(xtplug->child_widget);
xevent.xfocus.display = XtDisplay(xtplug->child_widget);
XSendEvent(XtDisplay(xtplug->child_widget),
xevent.xfocus.window,
False, NoEventMask,
&xevent );
XSync( XtDisplay(xtplug->child_widget), False);
}
break;
default:
break;
} /* End of XEmbed Message */
}
static void
xt_client_event_handler( Widget w, XtPointer client_data, XEvent *event)
{
XtClient *xtplug = (XtClient*)client_data;
switch(event->type)
{
case ClientMessage:
/* Handle xembed message */
if (event->xclient.message_type==
XInternAtom (XtDisplay(xtplug->child_widget),
"_XEMBED", False)) {
xt_client_handle_xembed_message(w, client_data, event);
}
break;
case ReparentNotify:
break;
case MappingNotify:
xt_client_set_info (w, XEMBED_MAPPED);
break;
case UnmapNotify:
xt_client_set_info (w, 0);
break;
case FocusIn:
send_xembed_message ( xtplug,
XEMBED_REQUEST_FOCUS, 0, 0, 0, 0);
break;
case FocusOut:
break;
case KeyPress:
#ifdef DEBUG_XTBIN
printf("Key Press Got!\n");
#endif
break;
default:
break;
} /* End of switch(event->type) */
}
static void
send_xembed_message (XtClient *xtclient,
long message,
long detail,
long data1,
long data2,
long time)
{
XEvent xevent;
Window w=XtWindow(xtclient->top_widget);
Display* dpy=xtclient->xtdisplay;
int errorcode;
memset(&xevent,0,sizeof(xevent));
xevent.xclient.window = w;
xevent.xclient.type = ClientMessage;
xevent.xclient.message_type = XInternAtom(dpy,"_XEMBED",False);
xevent.xclient.format = 32;
xevent.xclient.data.l[0] = time;
xevent.xclient.data.l[1] = message;
xevent.xclient.data.l[2] = detail;
xevent.xclient.data.l[3] = data1;
xevent.xclient.data.l[4] = data2;
trap_errors ();
XSendEvent (dpy, w, False, NoEventMask, &xevent);
XSync (dpy,False);
if((errorcode = untrap_errors())) {
#ifdef DEBUG_XTBIN
printf("send_xembed_message error(%d)!!!\n",errorcode);
#endif
}
}
static int
error_handler(Display *display, XErrorEvent *error)
{
trapped_error_code = error->error_code;
return 0;
}
static void
trap_errors(void)
{
trapped_error_code =0;
old_error_handler = XSetErrorHandler(error_handler);
}
static int
untrap_errors(void)
{
XSetErrorHandler(old_error_handler);
if(trapped_error_code) {
#ifdef DEBUG_XTBIN
printf("Get X Window Error = %d\n", trapped_error_code);
#endif
}
return trapped_error_code;
}
static void
xt_client_focus_listener( Widget w, XtPointer user_data, XEvent *event)
{
Display *dpy = XtDisplay(w);
XtClient *xtclient = user_data;
Window win = XtWindow(w);
switch(event->type)
{
case CreateNotify:
if(event->xcreatewindow.parent == win) {
Widget child=XtWindowToWidget( dpy, event->xcreatewindow.window);
if (child)
xt_add_focus_listener_tree(child, user_data);
}
break;
case DestroyNotify:
xt_remove_focus_listener( w, user_data);
break;
case ReparentNotify:
if(event->xreparent.parent == win) {
/* I am the new parent */
Widget child=XtWindowToWidget(dpy, event->xreparent.window);
if (child)
xt_add_focus_listener_tree( child, user_data);
}
else if(event->xreparent.window == win) {
/* I am the new child */
}
else {
/* I am the old parent */
}
break;
case ButtonRelease:
#if 0
XSetInputFocus(dpy, XtWindow(xtclient->child_widget), RevertToParent, event->xbutton.time);
#endif
send_xembed_message ( xtclient,
XEMBED_REQUEST_FOCUS, 0, 0, 0, 0);
break;
default:
break;
} /* End of switch(event->type) */
}
static void
xt_add_focus_listener( Widget w, XtPointer user_data)
{
XWindowAttributes attr;
long eventmask;
XtClient *xtclient = user_data;
int errorcode;
trap_errors ();
XGetWindowAttributes(XtDisplay(w), XtWindow(w), &attr);
eventmask = attr.your_event_mask | SubstructureNotifyMask | ButtonReleaseMask;
XSelectInput(XtDisplay(w),
XtWindow(w),
eventmask);
XtAddEventHandler(w,
SubstructureNotifyMask | ButtonReleaseMask,
TRUE,
(XtEventHandler)xt_client_focus_listener,
xtclient);
untrap_errors();
}
static void
xt_remove_focus_listener(Widget w, XtPointer user_data)
{
int errorcode;
trap_errors ();
XtRemoveEventHandler(w, SubstructureNotifyMask | ButtonReleaseMask, TRUE,
(XtEventHandler)xt_client_focus_listener, user_data);
untrap_errors();
}
static void
xt_add_focus_listener_tree ( Widget treeroot, XtPointer user_data)
{
Window win = XtWindow(treeroot);
Window *children;
Window root, parent;
Display *dpy = XtDisplay(treeroot);
unsigned int i, nchildren;
/* ensure we don't add more than once */
xt_remove_focus_listener( treeroot, user_data);
xt_add_focus_listener( treeroot, user_data);
trap_errors();
if(!XQueryTree(dpy, win, &root, &parent, &children, &nchildren)) {
untrap_errors();
return;
}
if(untrap_errors())
return;
for(i=0; i<nchildren; ++i) {
Widget child = XtWindowToWidget(dpy, children[i]);
if (child)
xt_add_focus_listener_tree( child, user_data);
}
XFree((void*)children);
return;
}

155
src/gtk2xtbin.h Normal file
View File

@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim:expandtab:shiftwidth=2:tabstop=2: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* 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 Gtk2XtBin Widget Implementation.
*
* The Initial Developer of the Original Code is
* Sun Microsystems, Inc.
* Portions created by the Initial Developer are Copyright (C) 2002
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __GTK_XTBIN_H__
#define __GTK_XTBIN_H__
#include <gtk/gtk.h>
#include <X11/Intrinsic.h>
#include <X11/Xutil.h>
#include <X11/Xlib.h>
#define GTKXTBIN_API(type) type
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct _GtkXtBin GtkXtBin;
typedef struct _GtkXtBinClass GtkXtBinClass;
#define GTK_TYPE_XTBIN (gtk_xtbin_get_type ())
#define GTK_XTBIN(obj) (GTK_CHECK_CAST ((obj), \
GTK_TYPE_XTBIN, GtkXtBin))
#define GTK_XTBIN_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \
GTK_TYPE_XTBIN, GtkXtBinClass))
#define GTK_IS_XTBIN(obj) (GTK_CHECK_TYPE ((obj), \
GTK_TYPE_XTBIN))
#define GTK_IS_XTBIN_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \
GTK_TYPE_XTBIN))
typedef struct _XtClient XtClient;
struct _XtClient {
Display *xtdisplay;
Widget top_widget; /* The toplevel widget */
Widget child_widget; /* The embedded widget */
Visual *xtvisual;
int xtdepth;
Colormap xtcolormap;
Window oldwindow;
};
struct _GtkXtBin
{
GtkSocket gsocket;
GdkWindow *parent_window;
Display *xtdisplay; /* Xt Toolkit Display */
Window xtwindow; /* Xt Toolkit XWindow */
gint x, y;
gint width, height;
XtClient xtclient; /* Xt Client for XEmbed */
};
struct _GtkXtBinClass
{
GtkSocketClass widget_class;
};
GTKXTBIN_API(GtkType) gtk_xtbin_get_type (void);
GTKXTBIN_API(GtkWidget *) gtk_xtbin_new (GdkWindow *parent_window,
Display *xtdisplay,
Visual *xtvisual,
Colormap xtcolormap,
int xtdepth);
GTKXTBIN_API(void) gtk_xtbin_set_position (GtkXtBin *xtbin,
gint x,
gint y);
GTKXTBIN_API(void) gtk_xtbin_resize (GtkWidget *widget,
gint width,
gint height);
typedef struct _XtTMRec {
XtTranslations translations; /* private to Translation Manager */
XtBoundActions proc_table; /* procedure bindings for actions */
struct _XtStateRec *current_state; /* Translation Manager state ptr */
unsigned long lastEventTime;
} XtTMRec, *XtTM;
typedef struct _CorePart {
Widget self; /* pointer to widget itself */
WidgetClass widget_class; /* pointer to Widget's ClassRec */
Widget parent; /* parent widget */
XrmName xrm_name; /* widget resource name quarkified */
Boolean being_destroyed; /* marked for destroy */
XtCallbackList destroy_callbacks; /* who to call when widget destroyed */
XtPointer constraints; /* constraint record */
Position x, y; /* window position */
Dimension width, height; /* window dimensions */
Dimension border_width; /* window border width */
Boolean managed; /* is widget geometry managed? */
Boolean sensitive; /* is widget sensitive to user events*/
Boolean ancestor_sensitive; /* are all ancestors sensitive? */
XtEventTable event_table; /* private to event dispatcher */
XtTMRec tm; /* translation management */
XtTranslations accelerators; /* accelerator translations */
Pixel border_pixel; /* window border pixel */
Pixmap border_pixmap; /* window border pixmap or NULL */
WidgetList popup_list; /* list of popups */
Cardinal num_popups; /* how many popups */
String name; /* widget resource name */
Screen *screen; /* window's screen */
Colormap colormap; /* colormap */
Window window; /* window ID */
Cardinal depth; /* number of planes in window */
Pixel background_pixel; /* window background pixel */
Pixmap background_pixmap; /* window background pixmap or NULL */
Boolean visible; /* is window mapped and not occluded?*/
Boolean mapped_when_managed;/* map window if it's managed? */
} CorePart;
typedef struct _WidgetRec {
CorePart core;
} WidgetRec, CoreRec;
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_XTBIN_H__ */

View File

@ -605,8 +605,10 @@ bool npobject_bridge_new(void)
void npobject_bridge_destroy(void)
{
g_hash_table_destroy(g_npobject_ids);
g_hash_table_destroy(g_npobjects);
if (g_npobject_ids)
g_hash_table_destroy(g_npobject_ids);
if (g_npobjects)
g_hash_table_destroy(g_npobjects);
}
void npobject_hash_table_insert(NPObject *npobj, NPObjectInfo *npobj_info)
@ -636,71 +638,3 @@ NPObject *npobject_lookup(uint32_t npobj_id)
{
return g_hash_table_lookup(g_npobject_ids, (void *)(uintptr_t)npobj_id);
}
/* ====================================================================== */
/* === Dummy npruntime accessors === */
/* ====================================================================== */
static void dummy_function_do_nothing(void)
{
}
static int dummy_function_return_zero(void)
{
return 0;
}
static bool dummy_function_return_void_variant(NPVariant *variant)
{
if (variant)
VOID_TO_NPVARIANT(*variant);
return false;
}
static bool dummy_NPN_Invoke(NPP npp, NPObject* obj, NPIdentifier methodName,
const NPVariant *args, uint32_t argCount, NPVariant *result)
{
return dummy_function_return_void_variant(result);
}
static bool dummy_NPN_InvokeDefault(NPP npp, NPObject* obj, const NPVariant *args,
uint32_t argCount, NPVariant *result)
{
return dummy_function_return_void_variant(result);
}
static bool dummy_NPN_Evaluate(NPP npp, NPObject* obj, NPString *script,
NPVariant *result)
{
return dummy_function_return_void_variant(result);
}
static bool dummy_NPN_GetProperty(NPP npp, NPObject* obj, NPIdentifier propertyName,
NPVariant *result)
{
return dummy_function_return_void_variant(result);
}
void npruntime_init_callbacks(NPNetscapeFuncs *mozilla_funcs)
{
mozilla_funcs->getstringidentifier = NewNPN_GetStringIdentifierProc(dummy_function_return_zero);
mozilla_funcs->getstringidentifiers = NewNPN_GetStringIdentifiersProc(dummy_function_do_nothing);
mozilla_funcs->getintidentifier = NewNPN_GetIntIdentifierProc(dummy_function_return_zero);
mozilla_funcs->identifierisstring = NewNPN_IdentifierIsStringProc(dummy_function_return_zero);
mozilla_funcs->utf8fromidentifier = NewNPN_UTF8FromIdentifierProc(dummy_function_return_zero);
mozilla_funcs->intfromidentifier = NewNPN_IntFromIdentifierProc(dummy_function_return_zero);
mozilla_funcs->createobject = NewNPN_CreateObjectProc(dummy_function_return_zero);
mozilla_funcs->retainobject = NewNPN_RetainObjectProc(dummy_function_return_zero);
mozilla_funcs->releaseobject = NewNPN_ReleaseObjectProc(dummy_function_do_nothing);
mozilla_funcs->invoke = NewNPN_InvokeProc(dummy_NPN_Invoke);
mozilla_funcs->invokeDefault = NewNPN_InvokeDefaultProc(dummy_NPN_InvokeDefault);
mozilla_funcs->evaluate = NewNPN_EvaluateProc(dummy_NPN_Evaluate);
mozilla_funcs->getproperty = NewNPN_GetPropertyProc(dummy_NPN_GetProperty);
mozilla_funcs->setproperty = NewNPN_SetPropertyProc(dummy_function_return_zero);
mozilla_funcs->removeproperty = NewNPN_RemovePropertyProc(dummy_function_return_zero);
mozilla_funcs->hasproperty = NewNPN_HasPropertyProc(dummy_function_return_zero);
mozilla_funcs->hasmethod = NewNPN_HasMethodProc(dummy_function_return_zero);
mozilla_funcs->releasevariantvalue = NewNPN_ReleaseVariantValueProc(dummy_function_do_nothing);
mozilla_funcs->setexception = NewNPN_SetExceptionProc(dummy_function_do_nothing);
}

178
src/npw-config-template.h Normal file
View File

@ -0,0 +1,178 @@
/*
* npw-config-template.h - nspluginwrapper configuration tool, template defs
*
* nspluginwrapper (C) 2005-2007 Gwenole Beauchesne
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef ELF_CLASS
#ifndef ElfW
# if ELF_CLASS == ELFCLASS32
# define ElfW(x) Elf32_ ## x
# define ELFW(x) ELF32_ ## x
# define FUNC(x) x ## _32
# define bswap_ad(x) bswap_32(x)
# else
# define ElfW(x) Elf64_ ## x
# define ELFW(x) ELF64_ ## x
# define FUNC(x) x ## _64
# define bswap_ad(x) bswap_64(x)
# endif
#endif
static void FUNC(elf_swap_ehdr)(ElfW(Ehdr) *hdr)
{
hdr->e_type = bswap_16(hdr->e_type);
hdr->e_machine = bswap_16(hdr->e_machine);
hdr->e_version = bswap_32(hdr->e_version);
hdr->e_entry = bswap_ad(hdr->e_entry);
hdr->e_phoff = bswap_ad(hdr->e_phoff);
hdr->e_shoff = bswap_ad(hdr->e_shoff);
hdr->e_flags = bswap_32(hdr->e_flags);
hdr->e_ehsize = bswap_16(hdr->e_ehsize);
hdr->e_phentsize = bswap_16(hdr->e_phentsize);
hdr->e_phnum = bswap_16(hdr->e_phnum);
hdr->e_shentsize = bswap_16(hdr->e_shentsize);
hdr->e_shnum = bswap_16(hdr->e_shnum);
hdr->e_shstrndx = bswap_16(hdr->e_shstrndx);
}
static void FUNC(elf_swap_shdr)(ElfW(Shdr) *shdr)
{
shdr->sh_name = bswap_32(shdr->sh_name);
shdr->sh_type = bswap_32(shdr->sh_type);
shdr->sh_flags = bswap_ad(shdr->sh_flags);
shdr->sh_addr = bswap_ad(shdr->sh_addr);
shdr->sh_offset = bswap_ad(shdr->sh_offset);
shdr->sh_size = bswap_ad(shdr->sh_size);
shdr->sh_link = bswap_32(shdr->sh_link);
shdr->sh_info = bswap_32(shdr->sh_info);
shdr->sh_addralign = bswap_ad(shdr->sh_addralign);
shdr->sh_entsize = bswap_ad(shdr->sh_entsize);
}
static void FUNC(elf_swap_sym)(ElfW(Sym) *sym)
{
sym->st_name = bswap_32(sym->st_name);
sym->st_value = bswap_ad(sym->st_value);
sym->st_size = bswap_ad(sym->st_size);
sym->st_shndx = bswap_16(sym->st_shndx);
}
static bool FUNC(is_elf_plugin_fd)(int fd, NPW_PluginInfo *out_plugin_info)
{
int i;
bool ret = false;
ElfW(Ehdr) ehdr;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
return false;
bool do_swap = (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) && !is_little_endian();
if (do_swap)
FUNC(elf_swap_ehdr)(&ehdr);
if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
return false;
if (ehdr.e_type != ET_DYN)
return false;
if (ehdr.e_version != EV_CURRENT)
return false;
if (out_plugin_info) {
const char *target_arch = "";
switch (ehdr.e_machine) {
case EM_386: target_arch = "i386"; break;
case EM_X86_64: target_arch = "x86_64"; break;
case EM_SPARC: target_arch = "sparc"; break;
case EM_PPC: target_arch = "ppc"; break;
case EM_PPC64: target_arch = "ppc64"; break;
}
strcpy(out_plugin_info->target_arch, target_arch);
const char *target_os = "";
switch (ehdr.e_ident[EI_OSABI]) {
case ELFOSABI_LINUX: target_os = "linux"; break;
case ELFOSABI_SOLARIS: target_os = "solaris"; break;
case ELFOSABI_FREEBSD: target_os = "freebsd"; break;
}
strcpy(out_plugin_info->target_os, target_os);
}
ElfW(Shdr) *shdr = (ElfW(Shdr) *)load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(*shdr));
if (do_swap) {
for (i = 0; i < ehdr.e_shnum; i++)
FUNC(elf_swap_shdr)(&shdr[i]);
}
char **sdata = (char **)calloc(ehdr.e_shnum, sizeof(*sdata));
for (i = 0; i < ehdr.e_shnum; i++) {
ElfW(Shdr) *sec = &shdr[i];
if (sec->sh_type != SHT_NOBITS)
sdata[i] = (char *)load_data(fd, sec->sh_offset, sec->sh_size);
}
ElfW(Shdr) *symtab_sec = NULL;
for (i = 0; i < ehdr.e_shnum; i++) {
ElfW(Shdr) *sec = &shdr[i];
if (sec->sh_type == SHT_DYNSYM
&& strcmp(sdata[ehdr.e_shstrndx] + sec->sh_name, ".dynsym") == 0) {
symtab_sec = sec;
break;
}
}
if (symtab_sec == NULL)
goto done;
ElfW(Sym) *symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
char *strtab = sdata[symtab_sec->sh_link];
int nb_syms = symtab_sec->sh_size / sizeof(*symtab);
if (do_swap) {
for (i = 0; i < nb_syms; i++)
FUNC(elf_swap_sym)(&symtab[i]);
}
int nb_np_syms;
int is_wrapper_plugin = 0;
for (i = 0, nb_np_syms = 0; i < nb_syms; i++) {
ElfW(Sym) *sym = &symtab[i];
const char *name = strtab + sym->st_name;
if (ELFW(ST_BIND)(sym->st_info) != STB_GLOBAL)
continue;
if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT && strcmp(name, "NPW_Plugin") == 0)
is_wrapper_plugin = 1;
if (ELFW(ST_TYPE)(sym->st_info) != STT_FUNC)
continue;
if (!strcmp(name, "NP_GetMIMEDescription") ||
!strcmp(name, "NP_Initialize") ||
!strcmp(name, "NP_Shutdown"))
nb_np_syms++;
}
ret = (nb_np_syms == 3) && !is_wrapper_plugin;
done:
for (i = 0; i < ehdr.e_shnum; i++)
free(sdata[i]);
free(sdata);
free(shdr);
return ret;
}
#undef bswap_ad
#undef ElfW
#undef ELFW
#undef FUNC
#undef ELF_CLASS
#endif

View File

@ -254,11 +254,31 @@ static const char **get_mozilla_plugin_dirs(void)
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
/* 32-bit ELF base types. */
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Word;
typedef uint32_t Elf32_Addr;
typedef uint32_t Elf32_Off;
#undef bswap_64
#define bswap_64(x) \
( \
(((x) & 0xff00000000000000) >> 56) | (((x) & 0x00ff000000000000) >> 40) | \
(((x) & 0x00000000000000ff) << 56) | (((x) & 0x000000000000ff00) << 40) | \
(((x) & 0x0000ff0000000000) >> 24) | (((x) & 0x000000ff00000000) >> 8) | \
(((x) & 0x0000000000ff0000) << 24) | (((x) & 0x00000000ff000000) << 8) \
)
/* 32-bit ELF base types. */
typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word;
/* 64-bit ELF base types. */
typedef uint64_t Elf64_Addr;
typedef uint16_t Elf64_Half;
typedef int16_t Elf64_SHalf;
typedef uint64_t Elf64_Off;
typedef int32_t Elf64_Sword;
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;
/* The ELF file header. This appears at the start of every ELF file. */
#define EI_NIDENT (16)
@ -281,6 +301,30 @@ typedef struct
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
/* Base structure - used to distinguish between 32/64 bit version */
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
} Elf_hdr_base;
#define EI_MAG0 0 /* File identification byte 0 index */
#define ELFMAG0 0x7f /* Magic number byte 0 */
#define EI_MAG1 1 /* File identification byte 1 index */
@ -326,6 +370,21 @@ typedef struct
Elf32_Word sh_entsize; /* Entry size if section holds table */
} Elf32_Shdr;
typedef struct
{
Elf64_Word sh_name; /* Section name, index in string tbl */
Elf64_Word sh_type; /* Type of section */
Elf64_Xword sh_flags; /* Miscellaneous section attributes */
Elf64_Addr sh_addr; /* Section virtual addr at execution */
Elf64_Off sh_offset; /* Section file offset */
Elf64_Xword sh_size; /* Size of section in bytes */
Elf64_Word sh_link; /* Index of another section */
Elf64_Word sh_info; /* Additional section information */
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
#define SHT_NOBITS 8 /* Program space with no data (bss) */
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
@ -340,18 +399,27 @@ typedef struct
Elf32_Half st_shndx; /* Section index */
} Elf32_Sym;
#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
#define ELF32_ST_TYPE(val) ((val) & 0xf)
typedef struct
{
Elf64_Word st_name; /* Symbol name, index in string tbl */
unsigned char st_info; /* Type and binding attributes */
unsigned char st_other; /* No defined meaning, 0 */
Elf64_Half st_shndx; /* Associated section index */
Elf64_Addr st_value; /* Value of the symbol */
Elf64_Xword st_size; /* Associated symbol size */
} Elf64_Sym;
#define ELF_ST_BIND(x) ((x) >> 4)
#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf)
#define ELF32_ST_BIND(x) ELF_ST_BIND(x)
#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x)
#define ELF64_ST_BIND(x) ELF_ST_BIND(x)
#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x)
#define STB_GLOBAL 1 /* Global symbol */
#define STT_OBJECT 1 /* Symbol is a data object */
#define STT_FUNC 2 /* Symbol is a code object */
/* We handle 32-bit ELF plugins only */
#undef ELF_CLASS
#define ELF_CLASS ELFCLASS32
#define ElfW(x) Elf32_ ## x
#define ELFW(x) ELF32_ ## x
void *load_data(int fd, long offset, unsigned int size)
{
char *data = (char *)malloc(size);
@ -374,51 +442,16 @@ static bool is_little_endian(void)
return x.b[0] == 0x04;
}
static void elf_swap_ehdr(ElfW(Ehdr) *hdr)
{
hdr->e_type = bswap_16(hdr->e_type);
hdr->e_machine = bswap_16(hdr->e_machine);
hdr->e_version = bswap_32(hdr->e_version);
hdr->e_entry = bswap_32(hdr->e_entry);
hdr->e_phoff = bswap_32(hdr->e_phoff);
hdr->e_shoff = bswap_32(hdr->e_shoff);
hdr->e_flags = bswap_32(hdr->e_flags);
hdr->e_ehsize = bswap_16(hdr->e_ehsize);
hdr->e_phentsize = bswap_16(hdr->e_phentsize);
hdr->e_phnum = bswap_16(hdr->e_phnum);
hdr->e_shentsize = bswap_16(hdr->e_shentsize);
hdr->e_shnum = bswap_16(hdr->e_shnum);
hdr->e_shstrndx = bswap_16(hdr->e_shstrndx);
}
#define ELF_CLASS ELFCLASS32
#include "npw-config-template.h"
static void elf_swap_shdr(ElfW(Shdr) *shdr)
{
shdr->sh_name = bswap_32(shdr->sh_name);
shdr->sh_type = bswap_32(shdr->sh_type);
shdr->sh_flags = bswap_32(shdr->sh_flags);
shdr->sh_addr = bswap_32(shdr->sh_addr);
shdr->sh_offset = bswap_32(shdr->sh_offset);
shdr->sh_size = bswap_32(shdr->sh_size);
shdr->sh_link = bswap_32(shdr->sh_link);
shdr->sh_info = bswap_32(shdr->sh_info);
shdr->sh_addralign = bswap_32(shdr->sh_addralign);
shdr->sh_entsize = bswap_32(shdr->sh_entsize);
}
static void elf_swap_sym(ElfW(Sym) *sym)
{
sym->st_name = bswap_32(sym->st_name);
sym->st_value = bswap_32(sym->st_value);
sym->st_size = bswap_32(sym->st_size);
sym->st_shndx = bswap_32(sym->st_shndx);
}
#define ELF_CLASS ELFCLASS64
#include "npw-config-template.h"
static bool is_plugin_fd(int fd, NPW_PluginInfo *out_plugin_info)
{
int i;
bool ret = false;
ElfW(Ehdr) ehdr;
Elf_hdr_base ehdr;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
return false;
@ -428,91 +461,13 @@ static bool is_plugin_fd(int fd, NPW_PluginInfo *out_plugin_info)
|| ehdr.e_ident[EI_MAG3] != ELFMAG3)
return false;
bool do_swap = (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) && !is_little_endian();
if (do_swap)
elf_swap_ehdr(&ehdr);
lseek(fd, 0, SEEK_SET);
if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
return false;
if (ehdr.e_type != ET_DYN)
return false;
if (ehdr.e_version != EV_CURRENT)
return false;
if (out_plugin_info) {
const char *target_arch = "";
switch (ehdr.e_machine) {
case EM_386: target_arch = "i386"; break;
case EM_SPARC: target_arch = "sparc"; break;
case EM_PPC: target_arch = "ppc"; break;
}
strcpy(out_plugin_info->target_arch, target_arch);
const char *target_os = "";
switch (ehdr.e_ident[EI_OSABI]) {
case ELFOSABI_LINUX: target_os = "linux"; break;
case ELFOSABI_SOLARIS: target_os = "solaris"; break;
case ELFOSABI_FREEBSD: target_os = "freebsd"; break;
}
strcpy(out_plugin_info->target_os, target_os);
switch (ehdr.e_ident[EI_CLASS]) {
case ELFCLASS32: return is_elf_plugin_fd_32(fd, out_plugin_info);
case ELFCLASS64: return is_elf_plugin_fd_64(fd, out_plugin_info);
}
ElfW(Shdr) *shdr = (ElfW(Shdr) *)load_data(fd, ehdr.e_shoff, ehdr.e_shnum * sizeof(*shdr));
if (do_swap) {
for (i = 0; i < ehdr.e_shnum; i++)
elf_swap_shdr(&shdr[i]);
}
char **sdata = (char **)calloc(ehdr.e_shnum, sizeof(*sdata));
for (i = 0; i < ehdr.e_shnum; i++) {
ElfW(Shdr) *sec = &shdr[i];
if (sec->sh_type != SHT_NOBITS)
sdata[i] = (char *)load_data(fd, sec->sh_offset, sec->sh_size);
}
ElfW(Shdr) *symtab_sec = NULL;
for (i = 0; i < ehdr.e_shnum; i++) {
ElfW(Shdr) *sec = &shdr[i];
if (sec->sh_type == SHT_DYNSYM
&& strcmp(sdata[ehdr.e_shstrndx] + sec->sh_name, ".dynsym") == 0) {
symtab_sec = sec;
break;
}
}
if (symtab_sec == NULL)
goto done;
ElfW(Sym) *symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
char *strtab = sdata[symtab_sec->sh_link];
int nb_syms = symtab_sec->sh_size / sizeof(*symtab);
if (do_swap) {
for (i = 0; i < nb_syms; i++)
elf_swap_sym(&symtab[i]);
}
int nb_np_syms;
int is_wrapper_plugin = 0;
for (i = 0, nb_np_syms = 0; i < nb_syms; i++) {
ElfW(Sym) *sym = &symtab[i];
const char *name = strtab + sym->st_name;
if (ELFW(ST_BIND)(sym->st_info) != STB_GLOBAL)
continue;
if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT && strcmp(name, "NPW_Plugin") == 0)
is_wrapper_plugin = 1;
if (ELFW(ST_TYPE)(sym->st_info) != STT_FUNC)
continue;
if (!strcmp(name, "NP_GetMIMEDescription") ||
!strcmp(name, "NP_Initialize") ||
!strcmp(name, "NP_Shutdown"))
nb_np_syms++;
}
ret = (nb_np_syms == 3) && !is_wrapper_plugin;
done:
for (i = 0; i < ehdr.e_shnum; i++)
free(sdata[i]);
free(sdata);
free(shdr);
return ret;
return false;
}
enum {
@ -548,6 +503,12 @@ static int detect_plugin_viewer(const char *filename, NPW_PluginInfo *out_plugin
else
target_os_table[0] = NULL;
// don't wrap plugins for host OS/ARCH
if (out_plugin_info
&& out_plugin_info->target_arch && strcmp(out_plugin_info->target_arch, HOST_ARCH) == 0
&& out_plugin_info->target_os && strcmp(out_plugin_info->target_os, HOST_OS) == 0)
return EXIT_VIEWER_NATIVE;
for (int i = 0; i < target_arch_table_size; i++) {
const char *target_arch = target_arch_table[i];
if (target_arch == NULL)
@ -562,8 +523,6 @@ static int detect_plugin_viewer(const char *filename, NPW_PluginInfo *out_plugin
const char *target_os = target_os_table[j];
if (target_os == NULL)
continue;
if (strcmp(target_arch, HOST_ARCH) == 0 && strcmp(target_os, HOST_OS) == 0)
return EXIT_VIEWER_NATIVE; // don't wrap plugins for host OS/ARCH
char viewer_path[PATH_MAX];
sprintf(viewer_path, "%s/%s/%s", viewer_arch_path, target_os, NPW_VIEWER);
if (access(viewer_path, F_OK) != 0)

View File

@ -66,6 +66,7 @@ int rpc_type_of_NPPVariable(int variable)
switch (variable) {
case NPPVpluginNameString:
case NPPVpluginDescriptionString:
case NPPVformValue: // byte values of 0 does not appear in the UTF-8 encoding but for U+0000
type = RPC_TYPE_STRING;
break;
case NPPVpluginWindowBool:

View File

@ -37,6 +37,11 @@ enum {
RPC_METHOD_NPN_STATUS,
RPC_METHOD_NPN_PRINT_DATA,
RPC_METHOD_NPN_REQUEST_READ,
RPC_METHOD_NPN_NEW_STREAM,
RPC_METHOD_NPN_DESTROY_STREAM,
RPC_METHOD_NPN_WRITE,
RPC_METHOD_NPN_PUSH_POPUPS_ENABLED_STATE,
RPC_METHOD_NPN_POP_POPUPS_ENABLED_STATE,
RPC_METHOD_NPP_NEW,
RPC_METHOD_NPP_DESTROY,

File diff suppressed because it is too large Load Diff

View File

@ -71,15 +71,6 @@ if test "$ARCH" != "$TARGET_ARCH"; then
fi
fi
# Don't wrap host plugins
case " $@ " in
*" --test "*|*" -t "*)
if test "$TARGET_OS" = "$OS" -a "$TARGET_ARCH" = "$ARCH"; then
exit 20 # EXIT_VIEWER_NATIVE
fi
;;
esac
# Expand PATH for RealPlayer package on NetBSD (realplay)
if test "$OS" = "NetBSD"; then
REALPLAYER_HOME="/usr/pkg/lib/RealPlayer"

View File

@ -18,16 +18,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define _GNU_SOURCE 1 /* RTLD_DEFAULT */
#include "sysdeps.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <dlfcn.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/wait.h>
@ -94,12 +95,12 @@ typedef struct _PluginInstance {
typedef struct _StreamInstance {
NPStream *stream;
uint32_t stream_id;
int is_plugin_stream;
} StreamInstance;
// Prototypes
static void plugin_init(int is_NP_Initialize);
static void plugin_exit(void);
static pthread_mutex_t plugin_init_lock = PTHREAD_MUTEX_INITIALIZER;
// Helpers
#ifndef min
@ -140,12 +141,40 @@ static gboolean rpc_event_dispatch(GSource *source, GSourceFunc callback, gpoint
/* === Browser side plug-in API === */
/* ====================================================================== */
// Does browser have specified feature?
#define NPN_HAS_FEATURE(FEATURE) ((mozilla_funcs.version & 0xff) >= NPVERS_HAS_##FEATURE)
// NPN_MemAlloc
static inline void *g_NPN_MemAlloc(uint32 size)
{
return CallNPN_MemAllocProc(mozilla_funcs.memalloc, size);
}
// NPN_MemFree
static inline void g_NPN_MemFree(void* ptr)
{
CallNPN_MemFreeProc(mozilla_funcs.memfree, ptr);
}
// NPN_MemFlush
static inline uint32 g_NPN_MemFlush(uint32 size)
{
return CallNPN_MemFlushProc(mozilla_funcs.memflush, size);
}
// NPN_UserAgent
static const char *g_NPN_UserAgent(NPP instance)
{
if (mozilla_funcs.uagent == NULL)
return NULL;
return mozilla_funcs.uagent(instance);
}
static int handle_NPN_UserAgent(rpc_connection_t *connection)
{
D(bug("handle_NPN_UserAgent\n"));
const char *user_agent = mozilla_funcs.uagent ? mozilla_funcs.uagent(NULL) : NULL;
const char *user_agent = g_NPN_UserAgent(NULL);
return rpc_method_send_reply(connection, RPC_TYPE_STRING, user_agent, RPC_TYPE_INVALID);
}
@ -463,6 +492,237 @@ static int handle_NPN_RequestRead(rpc_connection_t *connection)
return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_INVALID);
}
// NPN_NewStream
static NPError g_NPN_NewStream(NPP instance, NPMIMEType type, const char *target, NPStream **stream)
{
if (mozilla_funcs.newstream == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if (stream == NULL)
return NPERR_INVALID_PARAM;
D(bug("NPN_NewStream instance=%p, type='%s', target='%s'\n", instance, type, target));
NPError ret = CallNPN_NewStreamProc(mozilla_funcs.newstream, instance, type, target, stream);
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
if (ret == NPERR_NO_ERROR) {
StreamInstance *stream_pdata = malloc(sizeof(*stream_pdata));
if (stream_pdata == NULL)
return NPERR_OUT_OF_MEMORY_ERROR;
memset(stream_pdata, 0, sizeof(*stream_pdata));
stream_pdata->stream = *stream;
stream_pdata->stream_id = id_create(stream_pdata);
stream_pdata->is_plugin_stream = 1;
(*stream)->pdata = stream_pdata;
}
else {
static const StreamInstance fake_StreamInstance = {
.stream = NULL,
.stream_id = 0
};
static const NPStream fake_NPStream = {
.pdata = (void *)&fake_StreamInstance,
.url = NULL,
.end = 0,
.lastmodified = 0,
.notifyData = NULL
};
*stream = (void *)&fake_NPStream;
}
return ret;
}
static int handle_NPN_NewStream(rpc_connection_t *connection)
{
D(bug("handle_NPN_NewStream\n"));
NPP instance;
char *type;
char *target;
int error = rpc_method_get_args(connection,
RPC_TYPE_NPP, &instance,
RPC_TYPE_STRING, &type,
RPC_TYPE_STRING, &target,
RPC_TYPE_INVALID);
if (error != RPC_ERROR_NO_ERROR) {
npw_perror("NPN_NewStream() get args", error);
return error;
}
NPStream *stream;
NPError ret = g_NPN_NewStream(instance, type, target, &stream);
if (type)
free(type);
if (target)
free(target);
return rpc_method_send_reply(connection,
RPC_TYPE_INT32, ret,
RPC_TYPE_UINT32, ((StreamInstance *)stream->pdata)->stream_id,
RPC_TYPE_STRING, stream->url,
RPC_TYPE_UINT32, stream->end,
RPC_TYPE_UINT32, stream->lastmodified,
RPC_TYPE_NP_NOTIFY_DATA, stream->notifyData,
RPC_TYPE_STRING, NPN_HAS_FEATURE(RESPONSE_HEADERS) ? stream->headers : NULL,
RPC_TYPE_INVALID);
}
// NPN_DestroySream
static NPError
g_NPN_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
{
if (mozilla_funcs.destroystream == NULL)
return NPERR_INVALID_FUNCTABLE_ERROR;
if (stream == NULL)
return NPERR_INVALID_PARAM;
// Mozilla calls NPP_DestroyStream() for its streams, keep stream
// info in that case
StreamInstance *stream_pdata = stream->pdata;
if (stream_pdata && stream_pdata->is_plugin_stream) {
id_remove(stream_pdata->stream_id);
free(stream->pdata);
stream->pdata = NULL;
}
D(bug("NPN_DestroyStream instance=%p, stream=%p, reason=%s\n",
instance, stream, string_of_NPReason(reason)));
NPError ret = CallNPN_DestroyStreamProc(mozilla_funcs.destroystream, instance, stream, reason);
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
return ret;
}
static int handle_NPN_DestroyStream(rpc_connection_t *connection)
{
D(bug("handle_NPN_DestroyStream\n"));
NPP instance;
NPStream *stream;
int32_t reason;
int error = rpc_method_get_args(connection,
RPC_TYPE_NPP, &instance,
RPC_TYPE_NP_STREAM, &stream,
RPC_TYPE_INT32, &reason,
RPC_TYPE_INVALID);
if (error != RPC_ERROR_NO_ERROR) {
npw_perror("NPN_DestroyStream() get args", error);
return error;
}
NPError ret = g_NPN_DestroyStream(instance, stream, reason);
return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_INVALID);
}
// NPN_Write
static int32 g_NPN_Write(NPP instance, NPStream *stream, int32 len, void *buf)
{
if (mozilla_funcs.write == NULL)
return -1;
if (stream == NULL)
return -1;
D(bug("NPP_Write instance=%p\n", instance));
int32 ret = CallNPN_WriteProc(mozilla_funcs.write, instance, stream, len, buf);
D(bug(" return: %d\n", ret));
return ret;
}
static int handle_NPN_Write(rpc_connection_t *connection)
{
D(bug("handle_NPN_Write\n"));
NPP instance;
NPStream *stream;
unsigned char *buf;
int32_t len;
int error = rpc_method_get_args(connection,
RPC_TYPE_NPP, &instance,
RPC_TYPE_NP_STREAM, &stream,
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, &len, &buf,
RPC_TYPE_INVALID);
if (error != RPC_ERROR_NO_ERROR) {
npw_perror("NPN_Write() get args", error);
return error;
}
int32 ret = g_NPN_Write(instance, stream, len, buf);
if (buf)
free(buf);
return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_INVALID);
}
// NPN_PushPopupsEnabledState
static void g_NPN_PushPopupsEnabledState(NPP instance, NPBool enabled)
{
if (mozilla_funcs.pushpopupsenabledstate == NULL)
return;
D(bug("NPN_PushPopupsEnabledState instance=%p, enabled=%d\n", instance, enabled));
CallNPN_PushPopupsEnabledStateProc(mozilla_funcs.pushpopupsenabledstate, instance, enabled);
D(bug(" done\n"));
}
static int handle_NPN_PushPopupsEnabledState(rpc_connection_t *connection)
{
D(bug("handle_NPN_PushPopupsEnabledState\n"));
NPP instance;
uint32_t enabled;
int error = rpc_method_get_args(connection,
RPC_TYPE_NPP, &instance,
RPC_TYPE_UINT32, &enabled,
RPC_TYPE_INVALID);
if (error != RPC_ERROR_NO_ERROR) {
npw_perror("NPN_PushPopupsEnabledState() get args", error);
return error;
}
g_NPN_PushPopupsEnabledState(instance, enabled);
return RPC_ERROR_NO_ERROR;
}
// NPN_PopPopupsEnabledState
static void g_NPN_PopPopupsEnabledState(NPP instance)
{
if (mozilla_funcs.poppopupsenabledstate == NULL)
return;
D(bug("NPN_PopPopupsEnabledState instance=%p\n", instance));
CallNPN_PopPopupsEnabledStateProc(mozilla_funcs.poppopupsenabledstate, instance);
D(bug(" done\n"));
}
static int handle_NPN_PopPopupsEnabledState(rpc_connection_t *connection)
{
D(bug("handle_NPN_PopPopupsEnabledState\n"));
NPP instance;
int error = rpc_method_get_args(connection,
RPC_TYPE_NPP, &instance,
RPC_TYPE_INVALID);
if (error != RPC_ERROR_NO_ERROR) {
npw_perror("NPN_PopPopupsEnabledState() get args", error);
return error;
}
g_NPN_PopPopupsEnabledState(instance);
return RPC_ERROR_NO_ERROR;
}
// NPN_CreateObject
static int handle_NPN_CreateObject(rpc_connection_t *connection)
{
@ -982,7 +1242,6 @@ g_NPP_New(NPMIMEType mime_type, NPP instance,
static NPError
invoke_NPP_Destroy(NPP instance, NPSavedData **save)
{
// XXX handle save area (transfer raw bytes but keep size information somewhere)
int error = rpc_method_invoke(g_rpc_connection,
RPC_METHOD_NPP_DESTROY,
RPC_TYPE_NPP, instance,
@ -1007,6 +1266,11 @@ invoke_NPP_Destroy(NPP instance, NPSavedData **save)
if (save)
*save = save_area;
else if (save_area) {
if (save_area->len > 0 && save_area->buf)
free(save_area->buf);
free(save_area);
}
return ret;
}
@ -1097,7 +1361,24 @@ invoke_NPP_GetValue(NPP instance, NPPVariable variable, void *value)
ret = NPERR_GENERIC_ERROR;
}
D(bug(" value: %s\n", str));
*((char **)value) = str; // XXX memory leak
switch (variable) {
case NPPVformValue:
// this is a '\0'-terminated UTF-8 string data allocated by NPN_MemAlloc()
if (ret == NPERR_NO_ERROR && str) {
char *utf8_str = g_NPN_MemAlloc(strlen(str) + 1);
if (utf8_str == NULL)
ret = NPERR_OUT_OF_MEMORY_ERROR;
else
strcpy(utf8_str, str);
free(str);
str = utf8_str;
}
break;
default:
// XXX memory leak (add to a deallocation pool?)
break;
}
*((char **)value) = str;
break;
}
case RPC_TYPE_INT32:
@ -1232,6 +1513,7 @@ invoke_NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool see
RPC_TYPE_UINT32, stream->end,
RPC_TYPE_UINT32, stream->lastmodified,
RPC_TYPE_NP_NOTIFY_DATA, stream->notifyData,
RPC_TYPE_STRING, NPN_HAS_FEATURE(RESPONSE_HEADERS) ? stream->headers : NULL,
RPC_TYPE_BOOLEAN, seekable,
RPC_TYPE_INVALID);
@ -1269,6 +1551,7 @@ g_NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable
memset(stream_pdata, 0, sizeof(*stream_pdata));
stream_pdata->stream = stream;
stream_pdata->stream_id = id_create(stream_pdata);
stream_pdata->is_plugin_stream = 0;
stream->pdata = stream_pdata;
D(bug("NPP_NewStream instance=%p\n", instance));
@ -1391,7 +1674,7 @@ static int32
g_NPP_WriteReady(NPP instance, NPStream *stream)
{
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
return -1;
D(bug("NPP_WriteReady instance=%p\n", instance));
int32 ret = invoke_NPP_WriteReady(instance, stream);
@ -1434,7 +1717,7 @@ static int32
g_NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buf)
{
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
return -1;
D(bug("NPP_Write instance=%p\n", instance));
int32 ret = invoke_NPP_Write(instance, stream, offset, len, buf);
@ -1590,6 +1873,442 @@ NP_GetMIMEDescription(void)
return g_plugin.formats;
}
/* ====================================================================== */
/* === LONG64 NPAPI support === */
/* ====================================================================== */
/*
* Dependent on NPSavedData
* NPP_New
* NPP_Destroy
* NOTE: the browsers don't seem to care about NPSavedData
*
* Dependent on NPWindow / NPSetWindowCallbackStruct
* NPP_SetWindow
*
* Dependent on NPStream (plug-in side)
* NPP_NewStream
* NPP_DestroyStream
* NPP_WriteReady
* NPP_Write
* NPP_StreamAsFile
*
* Dependent on NPStream (browser-side)
* NPN_RequestRead
* NPN_NewStream
* NPN_DestroyStream
* NPN_Write
* NOTE: Konqueror does not implement those
*
* Dependent on NPPrintCallbackStruct
* NPP_Print
*/
// Check if another thunking layer is necessary
static int g_use_long64_thunks = -1;
static void set_use_long64_thunks(bool enabled)
{
g_use_long64_thunks = enabled;
if (g_use_long64_thunks) {
// XXX update mozilla_funcs with g_LONG64_*() variants
}
}
#define NP_CVT32(VAL) ptr32->VAL = ptr64->VAL
#define NP_CVT64(VAL) ptr64->VAL = ptr32->VAL
// Check display is valid
static bool is_browser_display(Display *display)
{
Display *browser_display = NULL;
if (mozilla_funcs.getvalue == NULL)
return 0;
if (mozilla_funcs.getvalue(NULL, NPNVxDisplay, (void *)&browser_display) != NPERR_NO_ERROR)
return 0;
return display == browser_display;
}
// NPStream
typedef struct _LONG64_NPStream {
void* pdata;
void* ndata;
const char* url;
uint64 end;
uint64 lastmodified;
void* notifyData;
const char* headers;
} LONG64_NPStream;
static void convert_from_LONG64_NPStream(NPStream *ptr32, const LONG64_NPStream *ptr64)
{
NP_CVT32(pdata);
NP_CVT32(ndata);
NP_CVT32(url);
NP_CVT32(end);
NP_CVT32(lastmodified);
NP_CVT32(notifyData);
NP_CVT32(headers);
}
#define NP_STREAM32(STREAM) get_stream32(STREAM)
static inline NPStream *get_stream32(LONG64_NPStream *stream64)
{
NPStream *stream32 = stream64->pdata;
if (stream32 && stream32->ndata == stream64)
return stream32;
return (NPStream *)stream64;
}
// NPByteRange
typedef struct _LONG64_NPByteRange {
int64 offset;
uint64 length;
struct _LONG64_NPByteRange* next;
} LONG64_NPByteRange;
// NPSavedData
typedef struct _LONG64_NPSavedData {
int64 len;
void* buf;
} LONG64_NPSavedData;
static void convert_from_LONG64_NPSavedData(NPSavedData *ptr32, const LONG64_NPSavedData *ptr64)
{
NP_CVT32(len);
NP_CVT32(buf);
}
static void convert_from_NPSavedData(LONG64_NPSavedData *ptr64, const NPSavedData *ptr32)
{
NP_CVT64(len);
NP_CVT64(buf);
}
// NPSetWindowCallbackStruct
typedef struct {
int64 type;
#ifdef MOZ_X11
Display* display;
Visual* visual;
Colormap colormap;
unsigned int depth;
#endif
} LONG64_NPSetWindowCallbackStruct;
static bool is_LONG64_NPSetWindowCallbackStruct(void *ws_info)
{
LONG64_NPSetWindowCallbackStruct *ws_info64 = (LONG64_NPSetWindowCallbackStruct *)ws_info;
return (/* LONG64_NPSetWindowCallbacStruct.type valid? */
(ws_info64->type == 0 || ws_info64->type == NP_SETWINDOW) &&
#ifdef MOZ_X11
/* LONG64_NPSetWindowCallbacStruct.display valid? */
is_browser_display(ws_info64->display) &&
#endif
1);
}
static void convert_from_LONG64_NPSetWindowCallbackStruct(NPSetWindowCallbackStruct *ptr32,
const LONG64_NPSetWindowCallbackStruct *ptr64)
{
NP_CVT32(type);
#ifdef MOZ_X11
NP_CVT32(display);
NP_CVT32(visual);
NP_CVT32(colormap);
NP_CVT32(depth);
#endif
}
// NPPrintCallbackStruct
typedef struct {
int64 type;
FILE* fp;
} LONG64_NPPrintCallbackStruct;
static bool is_LONG64_NPPrintCallbackStruct(void *platformPrint)
{
LONG64_NPPrintCallbackStruct *platformPrint64 = (LONG64_NPPrintCallbackStruct *)platformPrint;
return (/* LONG64_NPPrintCallbackStruct.type valid? */
platformPrint64->type == NP_PRINT &&
/* LONG64_NPPrintCallbackStruct.file valid? */
platformPrint64->fp != NULL);
}
static void convert_from_LONG64_NPPrintCallbackStruct(NPPrintCallbackStruct *ptr32,
const LONG64_NPPrintCallbackStruct *ptr64)
{
NP_CVT32(type);
NP_CVT32(fp);
}
// NPWindow
typedef struct _LONG64_NPWindow {
void* window;
int64 x;
int64 y;
uint64 width;
uint64 height;
NPRect clipRect;
#if defined(XP_UNIX) && !defined(XP_MACOSX)
void * ws_info;
#endif /* XP_UNIX */
NPWindowType type;
} LONG64_NPWindow;
static bool is_LONG64_NPWindow(void *window)
{
NPWindow *window32 = (NPWindow *)window;
LONG64_NPWindow *window64 = (LONG64_NPWindow *)window;
return (/* MSW32(LONG64_NPWindow.x) */
(window32->x == 0 || window32->x == 0xffffffff) &&
/* MSW32(LONG64_NPWindow.y) */
(window32->width == 0 || window32->width == 0xffffffff) &&
/* LONG64_NPWindow.clipRect.top, LONG64_NPWindow.clipRect.left */
(window32->type != NPWindowTypeWindow && window32->type != NPWindowTypeDrawable) &&
/* LONG64_NPWindow.type valid? */
(window64->type == NPWindowTypeWindow || window64->type == NPWindowTypeDrawable) &&
/* LONG64_NPWindow.ws_info valid? */
is_LONG64_NPSetWindowCallbackStruct(window64->ws_info));
}
static void convert_from_LONG64_NPWindow(NPWindow *ptr32, const LONG64_NPWindow *ptr64)
{
NP_CVT32(type);
NP_CVT32(window);
NP_CVT32(x);
NP_CVT32(y);
NP_CVT32(width);
NP_CVT32(height);
NP_CVT32(clipRect.top);
NP_CVT32(clipRect.left);
NP_CVT32(clipRect.bottom);
NP_CVT32(clipRect.right);
convert_from_LONG64_NPSetWindowCallbackStruct(ptr32->ws_info, ptr64->ws_info);
}
// NPP_SetWindow (LONG64)
static NPError
g_LONG64_NPP_SetWindow(NPP instance, void *window)
{
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
// Detect broken 64-bit NPAPI
if (g_use_long64_thunks < 0)
set_use_long64_thunks(is_LONG64_NPWindow(window));
NPWindow window32;
NPSetWindowCallbackStruct ws_info32;
if (g_use_long64_thunks) {
window32.ws_info = &ws_info32;
convert_from_LONG64_NPWindow(&window32, window);
window = &window32;
}
return g_NPP_SetWindow(instance, window);
}
// NPP_New (LONG64)
static NPError
g_LONG64_NPP_New(NPMIMEType mime_type, NPP instance,
uint16_t mode, int16_t argc, char *argn[], char *argv[],
void *saved)
{
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPSavedData saved32;
if (saved && g_use_long64_thunks > 0) {
convert_from_LONG64_NPSavedData(&saved32, saved);
saved = &saved32;
}
return g_NPP_New(mime_type, instance, mode, argc, argn, argv, saved);
}
// NPP_Destroy (LONG64)
static NPError
g_LONG64_NPP_Destroy(NPP instance, void **save)
{
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
NPSavedData *save_area32 = NULL;
NPError ret = g_NPP_Destroy(instance, &save_area32);
if (save && g_use_long64_thunks > 0) {
LONG64_NPSavedData *save_area64 = NULL;
if (ret == NPERR_NO_ERROR && save_area32) {
if ((save_area64 = g_NPN_MemAlloc(save_area32->len)) != NULL)
convert_from_NPSavedData(save_area64, save_area32);
free(save_area32);
}
*save = save_area64;
}
return ret;
}
// NPP_NewStream (LONG64)
static NPError
g_LONG64_NPP_NewStream(NPP instance, NPMIMEType type, void *stream, NPBool seekable, uint16 *stype)
{
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
// Detect broken 64-bit NPAPI
if (g_use_long64_thunks < 0) {
npw_printf("WARNING: function using an NPStream was called too early, could not determine LONG64 data structure\n");
set_use_long64_thunks(false);
}
if (g_use_long64_thunks) {
NPStream *stream32;
if ((stream32 = malloc(sizeof(*stream32))) == NULL)
return NPERR_OUT_OF_MEMORY_ERROR;
convert_from_LONG64_NPStream(stream32, stream);
stream32->ndata = stream;
((NPStream *)stream)->pdata = stream32;
}
return g_NPP_NewStream(instance, type, NP_STREAM32(stream), seekable, stype);
}
// NPP_DestroyStream (LONG64)
static NPError
g_LONG64_NPP_DestroyStream(NPP instance, void *stream, NPReason reason)
{
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
if (stream == NULL)
return NPERR_INVALID_PARAM;
NPError ret = g_NPP_DestroyStream(instance, NP_STREAM32(stream), reason);
if (g_use_long64_thunks) {
free(((NPStream *)stream)->pdata);
((NPStream *)stream)->pdata = NULL;
}
return ret;
}
// NPP_WriteReady (LONG64)
static int64
g_LONG64_NPP_WriteReady(NPP instance, void *stream)
{
if (instance == NULL)
return -1L;
if (stream == NULL)
return -1L;
return (int64)(int32)g_NPP_WriteReady(instance, NP_STREAM32(stream));
}
// NPP_Write (LONG64)
static int64
g_LONG64_NPP_Write(NPP instance, void *stream, int64 offset, int64 len, void *buf)
{
if (instance == NULL)
return -1L;
if (stream == NULL)
return -1L;
return (int64)(int32)g_NPP_Write(instance, NP_STREAM32(stream), offset, len, buf);
}
// NPP_StreamAsFile (LONG64)
static void
g_LONG64_NPP_StreamAsFile(NPP instance, void *stream, const char *fname)
{
if (instance == NULL)
return;
if (stream == NULL)
return;
g_NPP_StreamAsFile(instance, NP_STREAM32(stream), fname);
}
// NPP_Print (LONG64)
static void g_LONG64_NPP_Print(NPP instance, void *PrintInfo)
{
if (instance == NULL)
return;
if (PrintInfo == NULL)
return;
// Detect broken 64-bit NPAPI
if (g_use_long64_thunks < 0)
set_use_long64_thunks(is_LONG64_NPPrintCallbackStruct(PrintInfo));
NPPrint PrintInfo32;
NPPrintCallbackStruct platformPrint32;
if (g_use_long64_thunks) {
memcpy(&PrintInfo32, PrintInfo, sizeof(PrintInfo32));
void *platformPrint;
switch (((NPPrint *)PrintInfo)->mode) {
case NP_FULL:
platformPrint = ((NPPrint *)PrintInfo)->print.fullPrint.platformPrint;
convert_from_LONG64_NPPrintCallbackStruct(&platformPrint32, platformPrint);
PrintInfo32.print.fullPrint.platformPrint = &platformPrint32;
break;
case NP_EMBED:
platformPrint = ((NPPrint *)PrintInfo)->print.embedPrint.platformPrint;
convert_from_LONG64_NPPrintCallbackStruct(&platformPrint32, platformPrint);
PrintInfo32.print.embedPrint.platformPrint = &platformPrint32;
break;
}
PrintInfo = &PrintInfo32;
}
g_NPP_Print(instance, PrintInfo);
}
/* ====================================================================== */
/* === Plug-in initialization === */
/* ====================================================================== */
// Detect Konqueror
static bool is_konqueror(void)
{
if (dlsym(RTLD_DEFAULT, "qApp") == NULL)
return false;
if (mozilla_funcs.getvalue == NULL)
return false;
Display *x_display = NULL;
if (mozilla_funcs.getvalue(NULL, NPNVxDisplay, (void *)&x_display) != NPERR_NO_ERROR)
return false;
XtAppContext x_app_context = NULL;
if (mozilla_funcs.getvalue(NULL, NPNVxtAppContext, (void *)&x_app_context) != NPERR_NO_ERROR)
return false;
if (x_display == NULL || x_app_context == NULL)
return false;
String name, class;
XtGetApplicationNameAndClass(x_display, &name, &class);
if (strcmp(name, "nspluginviewer") == 0)
return true;
// XXX user-agent string can be changed, but it's still an heuristic
const char *user_agent = g_NPN_UserAgent(NULL);
if (user_agent == NULL)
return false;
if (strstr(user_agent, "Konqueror") != NULL)
return true;
return false;
}
// Provides global initialization for a plug-in
NPError
NP_Initialize(NPNetscapeFuncs *moz_funcs, NPPluginFuncs *plugin_funcs)
@ -1630,6 +2349,21 @@ NP_Initialize(NPNetscapeFuncs *moz_funcs, NPPluginFuncs *plugin_funcs)
plugin_funcs->getvalue = NewNPP_GetValueProc(g_NPP_GetValue);
plugin_funcs->setvalue = NewNPP_SetValueProc(g_NPP_SetValue);
// override function table with an additional thunking layer for
// possibly broken 64-bit Konqueror versions (NPAPI 0.11)
if (is_konqueror() && sizeof(void *) == 8 && ! NPN_HAS_FEATURE(NPRUNTIME_SCRIPTING)) {
D(bug("Installing Konqueror workarounds\n"));
plugin_funcs->setwindow = NewNPP_SetWindowProc(g_LONG64_NPP_SetWindow);
plugin_funcs->newstream = NewNPP_NewStreamProc(g_LONG64_NPP_NewStream);
plugin_funcs->destroystream = NewNPP_DestroyStreamProc(g_LONG64_NPP_DestroyStream);
plugin_funcs->asfile = NewNPP_StreamAsFileProc(g_LONG64_NPP_StreamAsFile);
plugin_funcs->writeready = NewNPP_WriteReadyProc(g_LONG64_NPP_WriteReady);
plugin_funcs->write = NewNPP_WriteProc(g_LONG64_NPP_Write);
plugin_funcs->print = NewNPP_PrintProc(g_LONG64_NPP_Print);
plugin_funcs->newp = NewNPP_NewProc(g_LONG64_NPP_New);
plugin_funcs->destroy = NewNPP_DestroyProc(g_LONG64_NPP_Destroy);
}
if (g_plugin.initialized == 0 || g_plugin.initialized == 1)
plugin_init(1);
if (g_plugin.initialized <= 0)
@ -1638,17 +2372,13 @@ NP_Initialize(NPNetscapeFuncs *moz_funcs, NPPluginFuncs *plugin_funcs)
if (!npobject_bridge_new())
return NPERR_MODULE_LOAD_FAILED_ERROR;
// NPRuntime appeared in NPAPI >= 0.14
bool has_npruntime = true;
if ((moz_funcs->version >> 8) == 0 && (moz_funcs->version & 0xff) < 14)
has_npruntime = false;
// check that the browser doesn't lie
if (moz_funcs->size < (offsetof(NPNetscapeFuncs, setexception) + sizeof(NPN_SetExceptionUPP)))
has_npruntime = false;
// pass down common NPAPI version supported by both the underlying
// browser and the thunking capabilities of nspluginwrapper
uint32_t version = min(moz_funcs->version, plugin_funcs->version);
int error = rpc_method_invoke(g_rpc_connection,
RPC_METHOD_NP_INITIALIZE,
RPC_TYPE_UINT32, (uint32_t)has_npruntime,
RPC_TYPE_UINT32, (uint32_t)version,
RPC_TYPE_INVALID);
if (error != RPC_ERROR_NO_ERROR) {
@ -1707,13 +2437,8 @@ NP_Shutdown(void)
return ret;
}
/* ====================================================================== */
/* === Plug initialization === */
/* ====================================================================== */
// Initialize wrapper plugin and execute viewer
static void do_plugin_init(int is_NP_Initialize)
static void plugin_init(int is_NP_Initialize)
{
if (g_plugin.initialized < 0)
return;
@ -1754,28 +2479,30 @@ static void do_plugin_init(int is_NP_Initialize)
FILE *viewer_fp = popen(command, "r");
if (viewer_fp == NULL)
return;
char **strings[] = { &g_plugin.name, &g_plugin.description, &g_plugin.formats, NULL };
int i, error = 0;
for (i = 0; strings[i] != NULL; i++) {
int len;
if (fscanf(viewer_fp, "%d\n", &len) != 1) {
error = 1;
break;
}
char *str = malloc(len + 1);
char line[256];
while (fgets(line, sizeof(line), viewer_fp)) {
// Read line
int len = strlen(line);
if (len == 0)
str[0] = '\0';
else {
if (fgets(str, len, viewer_fp) == NULL) {
error = 1;
break;
continue;
line[len - 1] = '\0';
// Parse line
char tag[sizeof(line)];
if (sscanf(line, "%s %d", tag, &len) == 2) {
char *str = malloc(++len);
if (str && fgets(str, len, viewer_fp)) {
if (strcmp(tag, "PLUGIN_NAME") == 0)
g_plugin.name = str;
else if (strcmp(tag, "PLUGIN_DESC") == 0)
g_plugin.description = str;
else if (strcmp(tag, "PLUGIN_MIME") == 0)
g_plugin.formats = str;
}
}
*(strings[i]) = str;
}
pclose(viewer_fp);
if (error == 0)
g_plugin.initialized = 1;
g_plugin.initialized = 1;
}
if (!is_NP_Initialize)
@ -1817,6 +2544,11 @@ static void do_plugin_init(int is_NP_Initialize)
{ RPC_METHOD_NPN_STATUS, handle_NPN_Status },
{ RPC_METHOD_NPN_PRINT_DATA, handle_NPN_PrintData },
{ RPC_METHOD_NPN_REQUEST_READ, handle_NPN_RequestRead },
{ RPC_METHOD_NPN_NEW_STREAM, handle_NPN_NewStream },
{ RPC_METHOD_NPN_DESTROY_STREAM, handle_NPN_DestroyStream },
{ RPC_METHOD_NPN_WRITE, handle_NPN_Write },
{ RPC_METHOD_NPN_PUSH_POPUPS_ENABLED_STATE, handle_NPN_PushPopupsEnabledState },
{ RPC_METHOD_NPN_POP_POPUPS_ENABLED_STATE, handle_NPN_PopPopupsEnabledState },
{ RPC_METHOD_NPN_CREATE_OBJECT, handle_NPN_CreateObject },
{ RPC_METHOD_NPN_RETAIN_OBJECT, handle_NPN_RetainObject },
{ RPC_METHOD_NPN_RELEASE_OBJECT, handle_NPN_ReleaseObject },
@ -1909,15 +2641,8 @@ static void do_plugin_init(int is_NP_Initialize)
D(bug("--- INIT ---\n"));
}
static void plugin_init(int is_NP_Initialize)
{
pthread_mutex_lock(&plugin_init_lock);
do_plugin_init(is_NP_Initialize);
pthread_mutex_unlock(&plugin_init_lock);
}
// Kill NSPlugin Viewer process
static void do_plugin_exit(void)
static void plugin_exit(void)
{
D(bug("plugin_exit\n"));
@ -1964,13 +2689,6 @@ static void do_plugin_exit(void)
g_plugin.initialized = 0;
}
static void plugin_exit(void)
{
pthread_mutex_lock(&plugin_init_lock);
do_plugin_exit();
pthread_mutex_unlock(&plugin_init_lock);
}
static void __attribute__((destructor)) plugin_exit_sentinel(void)
{
plugin_exit();

50
src/xembed.h Normal file
View File

@ -0,0 +1,50 @@
/*
* xembed.h - XEMBED definitions
*
* nspluginwrapper (C) 2005-2007 Gwenole Beauchesne
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef XEMBED_H
#define XEMBED_H
// XEMBED messages
#define XEMBED_EMBEDDED_NOTIFY 0
#define XEMBED_WINDOW_ACTIVATE 1
#define XEMBED_WINDOW_DEACTIVATE 2
#define XEMBED_REQUEST_FOCUS 3
#define XEMBED_FOCUS_IN 4
#define XEMBED_FOCUS_OUT 5
#define XEMBED_FOCUS_NEXT 6
#define XEMBED_FOCUS_PREV 7
#define XEMBED_GRAB_KEY 8
#define XEMBED_UNGRAB_KEY 9
#define XEMBED_MODALITY_ON 10
#define XEMBED_MODALITY_OFF 11
// Non-standard messages
#define XEMBED_GTK_GRAB_KEY 108
#define XEMBED_GTK_UNGRAB_KEY 109
// Details for XEMBED_FOCUS_IN
#define XEMBED_FOCUS_CURRENT 0
#define XEMBED_FOCUS_FIRST 1
#define XEMBED_FOCUS_LAST 2
// Flags for _XEMBED_INFO
#define XEMBED_MAPPED (1 << 0)
#endif /* XEMBED_H */

View File

@ -30,5 +30,12 @@ Various sample data to exercise the NPAPI plugins compatibility layer
<li><p><b>Citrix ICA Client demo</b><br>
<a href="http://www.rentonlinesoftware.com/store/tryademo.asp">http://www.rentonlinesoftware.com/store/tryademo.asp</a>
</ul>
Individual testcases:
<ul>
<li><p>Debian bug <a
href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=435912">#435912</a> (focus problem)<br>
<a href="http://www.addictinggames.com/bloxors.html">http://www.addictinggames.com/bloxors.html</a>
</ul>
</body>
</html>

View File

@ -1,11 +1,13 @@
#define _GNU_SOURCE 1 /* RTLD_NEXT */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <unistd.h>
#include <X11/X.h>
#include <X11/Xlib.h>
@ -15,11 +17,12 @@
#include <X11/StringDefs.h>
static int g_debug_level = -1;
static int g_debug_level = 1;
static FILE *g_log_file = NULL;
void npw_printf(const char *format, ...)
{
#if 0
if (g_debug_level < 0) {
g_debug_level = 0;
const char *debug_str = getenv("NPW_DEBUG");
@ -38,6 +41,9 @@ void npw_printf(const char *format, ...)
if (log_file == NULL)
g_log_file = stderr;
}
#else
g_log_file = stderr;
#endif
if (g_debug_level > 0) {
va_list args;
@ -47,7 +53,102 @@ void npw_printf(const char *format, ...)
}
}
#define PREPARE_FUNC(NAME, RET, ARGS) \
static RET (*lib_##NAME) ARGS; \
if (lib_##NAME == NULL) \
lib_##NAME = dlsym(RTLD_NEXT, #NAME); \
assert(lib_##NAME != NULL)
#if 0
char *getenv(const char *name)
{
PREPARE_FUNC(getenv, char *, (const char *));
char *str = lib_getenv(name);
npw_printf("getenv '%s' => '%s'\n", name ? name : "<null>", str ? str : "<null>");
return str;
}
int putenv(char *string)
{
PREPARE_FUNC(putenv, int, (char *));
npw_printf("putenv '%s'\n", string ? string : "<null>");
return lib_putenv(string);
}
#endif
int XSetClassHints(Display *display, Window w, XClassHint *class_hints)
{
PREPARE_FUNC(XSetClassHints, int, (Display *, Window, XClassHint *));
npw_printf("XSetClassHints(window %p, class_hints { %s, '%s' }\n", w, class_hints->res_name, class_hints->res_class);
return lib_XSetClassHints(display, w, class_hints);
}
static void print_backtrace(void)
{
#if 0
#define N_LEVELS 64
void *trace[N_LEVELS];
int n_levels = backtrace(trace, sizeof(trace)/sizeof(trace[0]));
backtrace_symbols_fd(trace, n_levels, STDERR_FILENO);
#endif
}
Status XSendEvent(Display *display, Window w, Bool propagate, long event_mask, XEvent *event_send)
{
PREPARE_FUNC(XSendEvent, Status, (Display *, Window, Bool, long, XEvent *));
if (event_send && (1 || ((XAnyEvent *)event_send)->send_event)) {
npw_printf("XSendEvent(window %p, propagate %d, event_mask %08x, event type %d, SendEvent %x)\n",
w, propagate, event_mask, event_send->type, event_send->xany.send_event);
}
print_backtrace();
if (event_send->xclient.message_type == XInternAtom(display, "_XEMBED", False))
npw_printf("[X11] Handle XEMBED message %d for window %p\n", event_send->xclient.data.l[1], event_send->xany.window);
return lib_XSendEvent(display, w, propagate, event_mask, event_send);
}
#if 0
Window XCreateWindow(Display *display, Window parent, int x, int y,
unsigned int width, unsigned int height,
unsigned int border_width, int depth, unsigned int class, Visual *visual,
unsigned long valuemask, XSetWindowAttributes *attributes)
{
PREPARE_FUNC(XCreateWindow, Window, (Display *, Window, int, int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, Visual *, unsigned long, XSetWindowAttributes *));
Window ret = lib_XCreateWindow(display, parent, x, y, width, height,
border_width, depth, class, visual,
valuemask, attributes);
npw_printf("[X11] XCreateWindow() -> %p\n", ret);
return ret;
}
#endif
#if 0
int XChangeProperty(Display *display, Window w, Atom property, Atom type,
int format, int mode, const unsigned char *data, int nelements)
{
PREPARE_FUNC(XChangeProperty, int, (Display *, Window, Atom, Atom, int, int, const unsigned char *, int));
const char *property_str = XGetAtomName(display, property);
const char *type_str = XGetAtomName(display, type);
npw_printf("XChangeProperty(window %p, property %s, type %s, format %d, mode %d)\n",
w, property_str, type_str, format, mode);
int ret = lib_XChangeProperty(display, w, property, type, format, mode, data, nelements);
if (property == XInternAtom(display, "WM_HINTS", False) && format == 32) {
XWMHints *hints = XGetWMHints(display, w);
if (hints) {
npw_printf(" InputHint %d\n", hints->input);
XFree((void *)hints);
}
}
return ret;
}
#endif
void XtConfigureWidget(Widget w, Position x, Position y, Dimension width, Dimension height, Dimension border_width)
{
PREPARE_FUNC(XtConfigureWidget, void, (Widget, Position, Position, Dimension, Dimension, Dimension));
lib_XtConfigureWidget(w, x, y, width, height, border_width);
}
#if 0
Atom XInternAtom(Display *display, const char *atom_name, Bool only_if_exists)
{
static Atom (*x_XInternAtom)(Display *, const char *, Bool) = NULL;
@ -58,21 +159,38 @@ Atom XInternAtom(Display *display, const char *atom_name, Bool only_if_exists)
Atom ret = x_XInternAtom(display, atom_name, only_if_exists);
return ret;
}
#endif
static XtEventHandler app_event_handler = NULL;
typedef struct {
void *client_data;
XtEventHandler event_handler;
} fake_event_handler_data;
static void fake_event_handler(Widget w, XtPointer client_data, XEvent *event, Boolean *cont)
{
fake_event_handler_data *pdata = (fake_event_handler_data *)client_data;
switch (event->type) {
case ButtonPress:
npw_printf("ButtonPress\n");
break;
case ButtonRelease:
npw_printf("ButtonRelease\n");
break;
case KeyPress:
npw_printf("KeyPress\n");
break;
case ButtonPress:
npw_printf("ButtonPress\n");
// asm volatile ("int3");
case KeyRelease:
npw_printf("KeyRelease\n");
break;
case FocusIn:
npw_printf("[X11] FocusIn for window %p\n", event->xfocus.window);
break;
case FocusOut:
npw_printf("[X11] FocusOut for window %p\n", event->xfocus.window);
break;
}
app_event_handler(w, client_data, event, cont);
pdata->event_handler(w, pdata->client_data, event, cont);
}
static const char *dlname(void *addr)
@ -83,6 +201,37 @@ static const char *dlname(void *addr)
return dlinfo.dli_sname;
}
static void print_event_mask(EventMask event_mask)
{
#define P(EVENT) if (event_mask & (EVENT##Mask)) npw_printf(" " #EVENT "\n")
P(KeyPress);
P(KeyRelease);
P(ButtonPress);
P(ButtonRelease);
P(EnterWindow);
P(LeaveWindow);
P(PointerMotion);
P(PointerMotionHint);
P(Button1Motion);
P(Button2Motion);
P(Button3Motion);
P(Button4Motion);
P(Button5Motion);
P(ButtonMotion);
P(KeymapState);
P(Exposure);
P(VisibilityChange);
P(StructureNotify);
P(ResizeRedirect);
P(SubstructureNotify);
P(SubstructureRedirect);
P(FocusChange);
P(PropertyChange);
P(ColormapChange);
P(OwnerGrabButton);
}
#if 1
void XtAddEventHandler(Widget w, EventMask event_mask, Bool nonmaskable,
XtEventHandler proc, XtPointer client_data)
{
@ -90,15 +239,67 @@ void XtAddEventHandler(Widget w, EventMask event_mask, Bool nonmaskable,
if (x_XtAddEventHandler == NULL)
x_XtAddEventHandler = dlsym(RTLD_NEXT, "XtAddEventHandler");
npw_printf("[X11] XtAddEventHandler(Widget=%p[0x%08x], event_mask=%x, nonmaskable=%d, proc=%p[%s])\n",
w, XtWindow(w), event_mask, nonmaskable, proc, dlname(proc));
if (event_mask & ButtonPressMask) {
app_event_handler = proc;
proc = fake_event_handler;
if (0 || (event_mask & (KeyPressMask|KeyReleaseMask))) {
npw_printf("[X11] XtAddEventHandler(Widget=%p[0x%08x], event_mask=%x, nonmaskable=%d, proc=%p[%s])\n",
w, XtWindow(w), event_mask, nonmaskable, proc, dlname(proc));
print_event_mask(event_mask);
}
#if 1
if (event_mask & (KeyPressMask|KeyReleaseMask)) {
fake_event_handler_data *pdata = malloc(sizeof(*pdata));
pdata->client_data = client_data;
pdata->event_handler = proc;
proc = fake_event_handler;
client_data = pdata;
}
#endif
x_XtAddEventHandler(w, event_mask, nonmaskable, proc, client_data);
#if 0
if (event_mask & (KeyPressMask|KeyReleaseMask))
x_XtAddEventHandler(w, event_mask, nonmaskable, fake_event_handler, client_data);
#endif
}
#endif
#if 0
void XtAddCallback(Widget w, _Xconst _XtString callback_name, XtCallbackProc callback, XtPointer client_data)
{
static void (*x_XtAddCallback)(Widget, _Xconst _XtString, XtCallbackProc, XtPointer);
if (x_XtAddCallback == NULL)
x_XtAddCallback = dlsym(RTLD_NEXT, "XtAddCallback");
npw_printf("[X11] XtAddCallback(widget %p[0x%08x], callback_name '%s', callback %p[%s], client_data %p)\n",
w, XtWindow(w), callback_name, callback, dlname(callback), client_data);
x_XtAddCallback(w, callback_name, callback, client_data);
}
#endif
#if 0
int XtGrabKeyboard(Widget w, _XtBoolean owner_events, int pointer_mode, int keyboard_mode, Time time)
{
static int (*x_XtGrabKeyboard)(Widget, _XtBoolean, int, int, Time);
if (x_XtGrabKeyboard == NULL)
x_XtGrabKeyboard = dlsym(RTLD_NEXT, "XtGrabKeyboard");
npw_printf("[X11] XtGrabKeyboard(widget %p[0x%08x], owner_events %08x, pointer_mode %08x, keyboard_mode %08x, time %d)\n",
w, XtWindow(w), owner_events, pointer_mode, keyboard_mode, time);
int rc = x_XtGrabKeyboard(w, owner_events, pointer_mode, keyboard_mode, time);
npw_printf(" returns %d\n", rc);
return rc;
}
void XtUngrabKeyboard(Widget w, Time time)
{
static void (*x_XtUngrabKeyboard)(Widget, Time);
if (x_XtUngrabKeyboard == NULL)
x_XtUngrabKeyboard = dlsym(RTLD_NEXT, "XtUngrabKeyboard");
npw_printf("[X11] XtUngrabKeyboard(widget %p[%08x], time %d)\n", w, XtWindow(w), time);
x_XtUngrabKeyboard(w, time);
}
#endif
#if 0
XtIntervalId XtAppAddTimeOut(XtAppContext app_context, unsigned long
interval, XtTimerCallbackProc proc, XtPointer client_data)
{
@ -143,7 +344,9 @@ Status XGetWindowAttributes(Display *display, Window w, XWindowAttributes *attr)
attr->x, attr->y, attr->width, attr->height, attr->border_width);
return ret;
}
#endif
#if 1
Widget XtCreatePopupShell(const char *name, WidgetClass widget_class, Widget
parent, ArgList args, Cardinal num_args)
{
@ -159,6 +362,7 @@ Widget XtCreatePopupShell(const char *name, WidgetClass widget_class, Widget
npw_printf(" return: %p [0x%08x]\n", ret, XtWindow(ret));
return ret;
}
#endif
#if 0
Status XQueryTree(Display *display, Window w, Window *root_return, Window *parent_return,
@ -180,7 +384,6 @@ Status XQueryTree(Display *display, Window w, Window *root_return, Window *paren
}
return ret;
}
#endif
Bool XQueryPointer(Display *display, Window w, Window *root_return,
Window *child_return, int *root_x_return, int *root_y_return,
@ -201,6 +404,7 @@ Bool XQueryPointer(Display *display, Window w, Window *root_return,
}
return ret;
}
#endif
#if 0
Widget XtWindowToWidget(Display *display, Window window)
@ -214,7 +418,6 @@ Widget XtWindowToWidget(Display *display, Window window)
npw_printf(" return: %p\n", ret);
return ret;
}
#endif
Widget XtParent(Widget w)
{
@ -227,7 +430,9 @@ Widget XtParent(Widget w)
npw_printf(" return: 0x%08x\n", ret);
return ret;
}
#endif
#if 0
static XErrorHandler app_error_handler = NULL;
static int fake_error_handler(Display *display, XErrorEvent *error_event)
@ -247,7 +452,9 @@ XErrorHandler XSetErrorHandler(XErrorHandler handler)
XErrorHandler ret = fn(fake_error_handler);
return ret;
}
#endif
#if 0
int XPutImage(Display *display, Drawable d, GC gc, XImage *image,
int src_x, int src_y, int dest_x, int dest_y, unsigned int width,
unsigned int height)
@ -282,3 +489,4 @@ Status XShmPutImage(Display *display, Drawable d, GC gc, XImage *image,
npw_printf(" return: %d\n", ret);
return ret;
}
#endif