Compare commits

..

60 Commits

Author SHA1 Message Date
blizzard%redhat.com
2ca39b9b17 merge from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53740 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-17 03:57:27 +00:00
blizzard%redhat.com
fe94a6ca17 merges from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53737 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-17 03:27:47 +00:00
blizzard%redhat.com
dbd81545d5 remove these files from the branch, they are elsewhere in head now...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53733 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-17 03:14:54 +00:00
blizzard%redhat.com
eae64955ac merge modal changes from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53660 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 16:15:13 +00:00
blizzard%redhat.com
ac2b83c0f5 merge IM fixes from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53656 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 16:08:54 +00:00
blizzard%redhat.com
4de4b9b262 merges from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53653 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 15:56:04 +00:00
(no author)
585367a7b8 This commit was manufactured by cvs2svn to create branch 'SUPERWIN'.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53594 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-16 01:52:21 +00:00
blizzard%redhat.com
8226158ae4 focus changes from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53447 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-14 04:34:41 +00:00
blizzard%redhat.com
9cb5b0bd0f don't clear the xlate queue for ConfigureEvents on shell windows since the xlate queue has nothing to do with that shell window...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53425 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-13 15:10:10 +00:00
blizzard%redhat.com
ac24bf46fe merges from head
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53408 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-13 04:55:21 +00:00
blizzard%redhat.com
feb3b49669 work around for lame NS_SIZE event problems...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53361 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 20:24:19 +00:00
blizzard%redhat.com
e4d84ceca8 use the external gtksuperwin library
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53360 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 20:14:52 +00:00
blizzard%redhat.com
63e9105b5f add gtksuperwin to the build list
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53359 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 20:13:40 +00:00
blizzard%redhat.com
21904a64db patch from claudius@netscape.com to make this build on platforms with picky c++ compilers
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53355 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 18:10:02 +00:00
blizzard%redhat.com
6d8df6d4e7 add a -lgtksuperwin for the viewer since it embeds a native widget into the layout
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53354 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 17:29:47 +00:00
blizzard%redhat.com
8f49d292ca merge in some of pav's IM changes...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53281 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-12 00:04:56 +00:00
pavlov%netscape.com
e1431cd937 fix loop in debugging code
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53251 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-11 22:03:47 +00:00
blizzard%redhat.com
d8ee1acce8 make sure that we do a gtk_style_attach() in the realize method so the style doesn't get destroyed early...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53241 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-11 21:39:27 +00:00
blizzard%redhat.com
db224b8d6e merge in clipboard changes. remove some more debugging spew.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53089 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-10 21:29:44 +00:00
blizzard%redhat.com
37106d7fc3 remove more debugging spew
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53088 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-10 21:05:38 +00:00
blizzard%redhat.com
0c074d2a55 remove debugging spew
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53086 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-10 19:35:01 +00:00
blizzard%redhat.com
7d47d3aace make sure to send focus in and focus out events properly when giving focus to a superwin.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53085 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-10 19:31:50 +00:00
blizzard%redhat.com
4d1a2e8639 merge the license whackage
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53020 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 23:06:12 +00:00
blizzard%redhat.com
8b6d035f17 add focus support
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53016 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 22:53:26 +00:00
blizzard%redhat.com
4d22490af1 fix warnings due to passing bad data to the debug code
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@53008 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 19:48:03 +00:00
blizzard%redhat.com
4a1d8f7401 fix bogus warnings for gtk_signal_emit_stop_by_name
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52997 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 17:20:22 +00:00
blizzard%redhat.com
3ed82d86a0 add nsWindow::SetCursor
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52996 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 17:10:22 +00:00
blizzard%redhat.com
e763644046 fix background colors on windows
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52995 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-09 17:03:43 +00:00
blizzard%redhat.com
e94c0535d1 add hacks for superwin
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52971 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:56:27 +00:00
blizzard%redhat.com
201eebe4ec add mozbox code
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52965 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:34:41 +00:00
blizzard%redhat.com
91802fc4cb add superwin code for mozbox
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52964 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:34:22 +00:00
pavlov%netscape.com
68a592d45f fix debugging stuff like flashing, etc
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52963 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 22:32:36 +00:00
blizzard%redhat.com
60c89eba4b export our gtk header files. we'll need them for embedding.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52953 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 21:52:35 +00:00
blizzard%redhat.com
ceecd95095 make sure that the child window uses the same destroy as the nsWindow class
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52950 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 21:40:54 +00:00
blizzard%redhat.com
220151a643 assert if we get passed bad data. this is for testing.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52944 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-08 16:11:10 +00:00
blizzard%redhat.com
35d00c2c83 only send resize events on windows that are toplevel or have been created with a native parent
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52930 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-07 19:31:15 +00:00
blizzard%redhat.com
dfccc12330 add nsWindow::SetBackgroundColor, fix a warning
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52923 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 20:39:28 +00:00
(no author)
3c0a628da5 This commit was manufactured by cvs2svn to create branch 'SUPERWIN'.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52913 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 03:43:57 +00:00
blizzard%redhat.com
e67e916ea6 turn off the backing store for now
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52889 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-06 00:30:53 +00:00
blizzard%redhat.com
2312b5fc11 fix problems with using nsWindow::WidgetToScreen with toplevel windows
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52863 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 21:37:52 +00:00
blizzard%redhat.com
fcb064c579 turn on backing store for the bin_window
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52856 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 16:39:20 +00:00
blizzard%redhat.com
72255234ea add expose event compression
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52854 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 15:58:56 +00:00
blizzard%redhat.com
2cff6771cb never assign a mozarea to mMozArea unless you own it.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52853 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 15:49:31 +00:00
pavlov%netscape.com
f16eb3c3d2 fix WidgetToScreen
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52850 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 06:05:37 +00:00
pavlov%netscape.com
cc5f4699b6 remove #ifdef GTK_FIXED crap. make USE_SUPERWIN default, and fix native system color stuff (to be in head soon)
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52845 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-05 05:45:52 +00:00
blizzard%redhat.com
8dbfb05c9f fix some refcounting problems with the superwin and mozarea
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52821 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 23:12:20 +00:00
blizzard%redhat.com
4f6c078a40 make sure to destroy the superwin when the object goes out of scope
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52806 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 21:51:50 +00:00
blizzard%redhat.com
f303b7b880 add queued drawing
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52803 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 21:16:21 +00:00
blizzard%redhat.com
d5d532bbdf make rollup events work.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52801 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 20:33:34 +00:00
blizzard%redhat.com
1e9545d94e scrolling added
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52797 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 20:06:53 +00:00
blizzard%redhat.com
bbaf2a8966 implement nsWindow::Resize and nsWindow::Move methods
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52772 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-04 03:25:04 +00:00
blizzard%redhat.com
4979b2734e first pass at getting superwin code to build. it will run now but doesn't have nsWindow::Move and nsWindow::Resize implemented...
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52747 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 23:07:52 +00:00
blizzard%redhat.com
0ba4ab32b2 fix some indenting issues
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52724 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 20:10:28 +00:00
blizzard%redhat.com
53df453f1a add gdk event handler
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52722 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 19:47:14 +00:00
blizzard%redhat.com
db90d4ddcf start adding glue code for events for the superwin and mozbox code. also, add the box and superwin as class members.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52721 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 18:58:37 +00:00
blizzard%redhat.com
24a4aec113 change all of the debugging calls to use GtkObject or GtkWidget
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52718 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 16:38:21 +00:00
blizzard%redhat.com
74599c2956 change all of the CreateNative calls to use GtkObject instead of GtkWidget
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52717 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 16:09:35 +00:00
(no author)
9b52dc355f This commit was manufactured by cvs2svn to create branch 'SUPERWIN'.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52698 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-03 07:34:51 +00:00
blizzard%redhat.com
1792ff0e46 start on the branch to get the superwin code to build.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52591 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 22:21:47 +00:00
(no author)
fb08d16e05 This commit was manufactured by cvs2svn to create branch 'SUPERWIN'.
git-svn-id: svn://10.0.0.236/branches/SUPERWIN@52461 18797224-902f-48f8-a5cc-f745e15eee43
1999-11-02 01:25:01 +00:00
88 changed files with 19303 additions and 11656 deletions

View File

@@ -0,0 +1,197 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public
PROGRAM = viewer
CPPSRCS = \
$(TOOLKIT_CPPSRCS) \
nsBaseDialog.cpp \
nsFindDialog.cpp \
nsXPBaseWindow.cpp \
nsTableInspectorDialog.cpp \
nsImageInspectorDialog.cpp \
nsPrintSetupDialog.cpp \
nsBrowserWindow.cpp \
nsEditorMode.cpp \
nsSetupRegistry.cpp \
nsThrobber.cpp \
nsViewerApp.cpp \
nsWebCrawler.cpp \
$(NULL)
EXPORT_RESOURCE_SAMPLES := \
$(wildcard $(srcdir)/samples/test*.html) \
$(wildcard $(srcdir)/samples/toolbarTest*.xul) \
$(wildcard $(srcdir)/samples/treeTest*.xul) \
$(wildcard $(srcdir)/samples/treeTest*.css) \
$(wildcard $(srcdir)/samples/slider*.xul) \
$(wildcard $(srcdir)/samples/scrollbar*.xul) \
$(srcdir)/resources/find.html \
$(srcdir)/resources/printsetup.html \
$(srcdir)/resources/image_props.html \
$(srcdir)/samples/aform.css \
$(srcdir)/samples/bform.css \
$(srcdir)/samples/cform.css \
$(srcdir)/samples/demoform.css \
$(srcdir)/samples/mozform.css \
$(srcdir)/samples/xulTest.css \
$(srcdir)/samples/Anieyes.gif \
$(srcdir)/samples/gear1.gif \
$(srcdir)/samples/rock_gra.gif \
$(srcdir)/samples/beeptest.html \
$(srcdir)/samples/soundtest.html \
$(srcdir)/samples/bg.jpg \
$(srcdir)/samples/raptor.jpg \
$(srcdir)/samples/test.wav \
$(srcdir)/samples/checkboxTest.xul \
$(NULL)
EXPORT_RESOURCE_THROBBER := $(wildcard $(srcdir)/throbber/anim*.gif)
ifeq (,$(filter beos os2 rhapsody photon,$(MOZ_WIDGET_TOOLKIT)))
DIRS += unix
UNIX_VIEWER_TK_LIBS = $(DIST)/lib/libviewer_$(MOZ_WIDGET_TOOLKIT)_s.a
else
ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
BEOS_PROGRAM_RESOURCE = $(srcdir)/viewer-beos.rsrc
TOOLKIT_CPPSRCS = nsBeOSMain.cpp
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),photon)
TOOLKIT_CPPSRCS = nsPhMain.cpp nsPhMenu.cpp
endif
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk)
GTK_GLUE = -lgtksuperwin
endif
ifdef MOZ_OJI
JSJ_LIB = -ljsj
endif
XP_DIST_LIBS = \
-lraptorgfx \
-lmozjs \
-lxpcom \
$(JSJ_LIB) \
$(NULL)
XP_NS_UNDERBAR_CRAP = \
$(MOZ_NECKO_UTIL_LIBS) \
$(MOZ_TIMER_LIBS) \
$(MOZ_WIDGET_SUPPORT_LIBS) \
$(NULL)
XP_LIBS = \
$(XP_NS_UNDERBAR_CRAP) \
$(XP_DIST_LIBS) \
$(NSPR_LIBS) \
$(NULL)
ifdef MOZ_FULLCIRCLE
XP_LIBS += $(FULLCIRCLE_LIBS)
endif
LIBS = \
$(UNIX_VIEWER_TK_LIBS) \
$(GTK_GLUE) \
$(XP_LIBS) \
$(TK_LIBS) \
$(NULL)
MOTIF_LIBS = -lviewer_motif_s $(XP_LIBS) $(MOZ_MOTIF_LDFLAGS)
QT_LIBS = -lviewer_qt_s $(XP_LIBS) $(MOZ_QT_LDFLAGS)
XLIB_LIBS = -lviewer_xlib_s $(XP_LIBS) $(MOZ_XLIB_LDFLAGS)
GTK_LIBS = -lviewer_gtk_s -lgtksuperwin $(XP_LIBS) $(MOZ_GTK_LDFLAGS)
EXTRA_DEPS = \
$(addprefix $(DIST)/,$(patsubst -l%,bin/lib%.$(DLL_SUFFIX),$(XP_DIST_LIBS:-l%_s=lib/lib%_s.a))) \
$(UNIX_VIEWER_TK_LIBS) \
$(XP_NS_UNDERBAR_CRAP) \
$(NULL)
include $(topsrcdir)/config/rules.mk
CXXFLAGS += $(MOZ_TOOLKIT_REGISTRY_CFLAGS)
install:: $(PROGRAM) $(srcdir)/mozilla-viewer.sh
$(INSTALL) $(EXPORT_RESOURCE_SAMPLES) $(DIST)/bin/res/samples
$(INSTALL) $(EXPORT_RESOURCE_THROBBER) $(DIST)/bin/res/throbber
$(INSTALL) $(srcdir)/resources/viewer.properties $(DIST)/bin/res
$(INSTALL) $(srcdir)/mozilla-viewer.sh $(DIST)/bin
$(PROGRAM)_gtk: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_gtk_s.a
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(GTK_LIBS) $(OS_LIBS)
$(MOZ_POST_PROGRAM_COMMAND) $@
$(PROGRAM)_motif: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_motif_s.a
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(MOTIF_LIBS) $(OS_LIBS)
$(MOZ_POST_PROGRAM_COMMAND) $@
$(PROGRAM)_qt: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_qt_s.a
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(QT_LIBS) $(OS_LIBS)
$(MOZ_POST_PROGRAM_COMMAND) $@
$(PROGRAM)_xlib: $(PROGOBJS) $(EXTRA_DEPS) Makefile Makefile.in $(DIST)/lib/libviewer_xlib_s.a
$(CCC) -o $@ $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(XLIB_LIBS) $(OS_LIBS)
$(MOZ_POST_PROGRAM_COMMAND) $@
ifdef MOZ_ENABLE_GTK
install:: $(PROGRAM)_gtk
$(INSTALL) -m 555 $< $(DIST)/bin
clobber::
rm -f $(PROGRAM)_gtk
endif
ifdef MOZ_ENABLE_MOTIF
install:: $(PROGRAM)_motif
$(INSTALL) -m 555 $< $(DIST)/bin
clobber::
rm -f $(PROGRAM)_motif
endif
ifdef MOZ_ENABLE_QT
install:: $(PROGRAM)_qt
$(INSTALL) -m 555 $< $(DIST)/bin
clobber::
rm -f $(PROGRAM)_qt
endif
ifdef MOZ_ENABLE_XLIB
install:: $(PROGRAM)_xlib
$(INSTALL) -m 555 $< $(DIST)/bin
clobber::
rm -f $(PROGRAM)_xlib
endif

View File

@@ -0,0 +1,179 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "gdksuperwin.h"
#include "gtkmozbox.h"
#include "nsBrowserWindow.h"
#include "resources.h"
#include "nscore.h"
#include "stdio.h"
typedef GtkItemFactoryCallback GIFC;
void gtk_ifactory_cb (nsBrowserWindow *nbw,
guint callback_action,
GtkWidget *widget)
{
nbw->DispatchMenuItem(callback_action);
}
GtkItemFactoryEntry menu_items[] =
{
{ "/_File", nsnull, nsnull, 0, "<Branch>" },
{ "/File/_New Window", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_WINDOW_OPEN, nsnull },
{ "/File/_Open...", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_FILE_OPEN, nsnull },
{ "/File/_View Source", nsnull, (GIFC)gtk_ifactory_cb, VIEW_SOURCE, nsnull },
{ "/File/_Samples", nsnull, nsnull, 0, "<Branch>" },
{ "/File/Samples/demo #0", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO0, nsnull },
{ "/File/Samples/demo #1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO1, nsnull },
{ "/File/Samples/demo #2", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO2, nsnull },
{ "/File/Samples/demo #3", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO3, nsnull },
{ "/File/Samples/demo #4", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO4, nsnull },
{ "/File/Samples/demo #5", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO5, nsnull },
{ "/File/Samples/demo #6", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO6, nsnull },
{ "/File/Samples/demo #7", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO7, nsnull },
{ "/File/Samples/demo #8", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO8, nsnull },
{ "/File/Samples/demo #9", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO9, nsnull },
{ "/File/Samples/demo #10", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO10, nsnull },
{ "/File/Samples/demo #11", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO11, nsnull },
{ "/File/Samples/demo #12", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO12, nsnull },
{ "/File/Samples/demo #13", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO13, nsnull },
{ "/File/Samples/demo #14", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO14, nsnull },
{ "/File/Samples/demo #15", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO15, nsnull },
{ "/File/Samples/demo #16", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO16, nsnull },
{ "/File/Samples/demo #17", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEMO17, nsnull },
{ "/File/_Test Sites", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOP100, nsnull },
{ "/File/XPToolkit Tests", nsnull, nsnull, 0, "<Branch>" },
{ "/File/XPToolkit Tests/Toolbar Test 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_XPTOOLKITTOOLBAR1, nsnull },
{ "/File/XPToolkit Tests/Tree Test 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_XPTOOLKITTREE1, nsnull },
{ "/File/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/File/Print Preview", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_ONE_COLUMN, nsnull },
{ "/File/Print", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_PRINT, nsnull },
{ "/File/Print Setup", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_PRINT_SETUP, nsnull },
{ "/File/sep2", nsnull, nsnull, 0, "<Separator>" },
{ "/File/_Exit", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EXIT, nsnull },
{ "/_Edit", nsnull, nsnull, 0, "<Branch>" },
{ "/Edit/Cu_t", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_CUT, nsnull },
{ "/Edit/_Copy", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_COPY, nsnull },
{ "/Edit/_Paste", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_PASTE, nsnull },
{ "/Edit/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Edit/Select All", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_SELECTALL, nsnull },
{ "/Edit/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Edit/Find in Page", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_EDIT_FINDINPAGE, nsnull },
//#ifdef DEBUG // turning off for now
{ "/_Debug", nsnull, nsnull, 0, "<Branch>" },
{ "/Debug/_Visual Debugging", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_VISUAL_DEBUGGING,nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Event Debugging/Toggle Paint Flashing", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_PAINT_FLASHING,nsnull },
{ "/Debug/Event Debugging/Toggle Paint Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_PAINT_DUMPING,nsnull },
{ "/Debug/Event Debugging/Toggle Invalidate Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_INVALIDATE_DUMPING,nsnull },
{ "/Debug/Event Debugging/Toggle Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_EVENT_DUMPING,nsnull },
{ "/Debug/Event Debugging/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Event Debugging/Toggle Motion Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_MOTION_EVENT_DUMPING,nsnull },
{ "/Debug/Event Debugging/Toggle Crossing Event Dumping", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_CROSSING_EVENT_DUMPING,nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/_Reflow Test", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_REFLOW_TEST, nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Dump _Content", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_CONTENT, nsnull },
{ "/Debug/Dump _Frames", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_FRAMES, nsnull },
{ "/Debug/Dump _Views", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_VIEWS, nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Dump _Style Sheets", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_STYLE_SHEETS, nsnull },
{ "/Debug/Dump _Style Contexts", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DUMP_STYLE_CONTEXTS, nsnull},
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Show Content Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_CONTENT_SIZE,nsnull },
{ "/Debug/Show Frame Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_FRAME_SIZE, nsnull },
{ "/Debug/Show Style Size", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_STYLE_SIZE, nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Debug Save", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEBUGSAVE, nsnull },
{ "/Debug/Debug Output Text", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DISPLAYTEXT, nsnull },
{ "/Debug/Debug Output HTML", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DISPLAYHTML, nsnull },
{ "/Debug/Debug Toggle Selection", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_TOGGLE_SELECTION,nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Debug Robot", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_DEBUGROBOT, nsnull },
{ "/Debug/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Debug/Show Content Quality", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SHOW_CONTENT_QUALITY, nsnull },
{ "/_Style", nsnull, nsnull, 0, "<Branch>" },
{ "/Style/Select _Style Sheet", nsnull, nsnull, 0, "<Branch>" },
{ "/Style/Select Style Sheet/List Available Sheets", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_LIST, nsnull },
{ "/Style/Select Style Sheet/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Style/Select Style Sheet/Select Default", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_DEFAULT, nsnull },
{ "/Style/Select Style Sheet/sep1", nsnull, nsnull, 0, "<Separator>" },
{ "/Style/Select Style Sheet/Select Alternative 1", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_ONE, nsnull },
{ "/Style/Select Style Sheet/Select Alternative 2", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_TWO, nsnull },
{ "/Style/Select Style Sheet/Select Alternative 3", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_THREE, nsnull },
{ "/Style/Select Style Sheet/Select Alternative 4", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_SELECT_STYLE_FOUR, nsnull },
{ "/Style/_Compatibility Mode", nsnull, nsnull, 0, "<Branch>" },
{ "/Style/Compatibility Mode/Nav Quirks", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_NAV_QUIRKS_MODE, nsnull },
{ "/Style/Compatibility Mode/Standard", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_STANDARD_MODE, nsnull },
{ "/Style/_Widget Render Mode", nsnull, nsnull, 0, "<Branch>" },
{ "/Style/Widget Render Mode/Native", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_NATIVE_WIDGET_MODE, nsnull },
{ "/Style/Widget Render Mode/Gfx", nsnull, (GIFC)gtk_ifactory_cb, VIEWER_GFX_WIDGET_MODE, nsnull },
//#endif
{ "/_Tools", nsnull, nsnull, 0, "<Branch>" },
{ "/Tools/_JavaScript Console", nsnull, (GIFC)gtk_ifactory_cb, JS_CONSOLE, nsnull },
{ "/Tools/_Editor Mode", nsnull, (GIFC)gtk_ifactory_cb, EDITOR_MODE, nsnull }
};
void CreateViewerMenus(nsIWidget * aParent,
gpointer data,
GtkWidget ** aMenuBarOut)
{
NS_ASSERTION(nsnull != aParent,"null parent.");
NS_ASSERTION(nsnull != aMenuBarOut,"null out param.");
GtkItemFactory *item_factory;
GtkWidget *menubar;
GdkSuperWin *gdkSuperWin;
GtkWidget *mozBox;
gdkSuperWin = (GdkSuperWin*)aParent->GetNativeData(NS_NATIVE_WIDGET);
int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", nsnull);
gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, data);
menubar = gtk_item_factory_get_widget (item_factory, "<main>");
gtk_menu_bar_set_shadow_type (GTK_MENU_BAR(menubar), GTK_SHADOW_NONE);
NS_ASSERTION(GDK_IS_SUPERWIN(gdkSuperWin), "code assumes a gdksuperwin.");
mozBox = gtk_mozbox_new(gdkSuperWin->bin_window);
NS_ASSERTION((mozBox != NULL), "failed to create mozBox.");
gtk_container_add(GTK_CONTAINER(mozBox), menubar);
gtk_mozbox_set_position(GTK_MOZBOX(mozBox), 0, 0 );
gtk_widget_show(mozBox);
gtk_widget_show(menubar);
*aMenuBarOut = menubar;
}

View File

@@ -1,135 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<!-- Coding standards for this document
* Other than the GFDL, please use the "section" tag instead of "sect1",
"sect2", etc.
* Use Entities to include files for new chapters in Bugzilla-Guide.xml.
* Try to use Entities for frequently-used passages of text as well.
* Ensure all documents compile cleanly to HTML after modification.
The warning, "DTDDECL catalog types not supported" is normal.
* Try to index important terms wherever possible.
* Use "glossterm" whenever you introduce a new term.
* Follow coding standards at http://www.tldp.org, and
check out the KDE guidelines (they are nice, too)
http://i18n.kde.org/doc/markup.html
* All tags should be lowercase.
* Please use sensible spacing. The comments at the very end of each
file define reasonable defaults for PSGML mode in EMACS.
* Double-indent tags, use double spacing whenever possible, and
try to avoid clutter and feel free to waste space in the code to make it
more readable.
-->
<book id="index">
<!-- Header -->
<bookinfo>
<title>The Bugzilla Guide - &bz-ver;
<!-- BZ-DEVEL -->Development <!-- /BZ-DEVEL -->
Release</title>
<authorgroup>
<corpauthor>The Bugzilla Team</corpauthor>
</authorgroup>
<pubdate>&bz-date;</pubdate>
<abstract>
<para>
This is the documentation for Bugzilla, a
bug-tracking system from mozilla.org.
Bugzilla is an enterprise-class piece of software
that tracks millions of bugs and issues for hundreds of
organizations around the world.
</para>
<para>
The most current version of this document can always be found on the
<ulink url="http://www.bugzilla.org/docs/">Bugzilla
Documentation Page</ulink>.
</para>
</abstract>
<keywordset>
<keyword>Bugzilla</keyword>
<keyword>Guide</keyword>
<keyword>installation</keyword>
<keyword>FAQ</keyword>
<keyword>administration</keyword>
<keyword>integration</keyword>
<keyword>MySQL</keyword>
<keyword>Mozilla</keyword>
<keyword>webtools</keyword>
</keywordset>
</bookinfo>
<!-- About This Guide -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="about.xml" />
<!-- Installing Bugzilla -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="installation.xml" />
<!-- Administering Bugzilla -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="administration.xml" />
<!-- Securing Bugzilla -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="security.xml" />
<!-- Customizing Bugzilla -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="customization.xml" />
<!-- Using Bugzilla -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="using.xml" />
<!-- Appendix: Troubleshooting -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="troubleshooting.xml" />
<!-- Appendix: Custom Patches -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="patches.xml" />
<!-- Appendix: Manually Installing Perl Modules -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules.xml" />
<!-- Appendix: GNU Free Documentation License -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="gfdl.xml" />
<!-- Glossary -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="glossary.xml" />
<!-- Index -->
<!--xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="index.xml" /-->
</book>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

View File

@@ -1,246 +0,0 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<!-- $Id: about.xml,v 1.26.4.1 2008-07-13 16:44:28 mozilla%colinogilvie.co.uk Exp $ -->
<chapter id="about">
<title>About This Guide</title>
<section id="copyright">
<title>Copyright Information</title>
<para>This document is copyright (c) 2000-&current-year; by the various
Bugzilla contributors who wrote it.</para>
<blockquote>
<para>
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation
License, Version 1.1 or any later version published by the
Free Software Foundation; with no Invariant Sections, no
Front-Cover Texts, and with no Back-Cover Texts. A copy of
the license is included in <xref linkend="gfdl"/>.
</para>
</blockquote>
<para>
If you have any questions regarding this document, its
copyright, or publishing this document in non-electronic form,
please contact the Bugzilla Team.
</para>
</section>
<section id="disclaimer">
<title>Disclaimer</title>
<para>
No liability for the contents of this document can be accepted.
Follow the instructions herein at your own risk.
This document may contain errors
and inaccuracies that may damage your system, cause your partner
to leave you, your boss to fire you, your cats to
pee on your furniture and clothing, and global thermonuclear
war. Proceed with caution.
</para>
<para>
Naming of particular products or brands should not be seen as
endorsements, with the exception of the term "GNU/Linux". We
wholeheartedly endorse the use of GNU/Linux; it is an extremely
versatile, stable,
and robust operating system that offers an ideal operating
environment for Bugzilla.
</para>
<para>
Although the Bugzilla development team has taken great care to
ensure that all exploitable bugs have been fixed, security holes surely
exist in any piece of code. Great care should be taken both in
the installation and usage of this software. The Bugzilla development
team members assume no liability for your use of Bugzilla. You have
the source code, and are responsible for auditing it yourself to ensure
your security needs are met.
</para>
</section>
<!-- Section 2: New Versions -->
<section id="newversions">
<title>New Versions</title>
<para>
This is the &bz-ver; version of The Bugzilla Guide. It is so named
to match the current version of Bugzilla.
<!-- BZ-DEVEL --> This version of the guide, like its associated Bugzilla version, is a
development version.<!-- /BZ-DEVEL -->
</para>
<para>
The latest version of this guide can always be found at <ulink
url="http://www.bugzilla.org"/>, or checked out via CVS by
following the <ulink url="http://www.mozilla.org/cvs.html">Mozilla
CVS</ulink> instructions and check out the
<filename>mozilla/webtools/bugzilla/docs/</filename>
subtree. However, you should read the version
which came with the Bugzilla release you are using.
</para>
<para>
The Bugzilla Guide, or a section of it, is also available in
the following languages:
<ulink url="http://www.traduc.org/docs/guides/lecture/bugzilla/">French</ulink>,
<ulink url="http://bugzilla-de.sourceforge.net/docs/html/">German</ulink>,
<ulink url="http://www.bugzilla.jp/docs/2.18/">Japanese</ulink>.
Note that these may be outdated or not up to date.
</para>
<para>
In addition, there are Bugzilla template localization projects in
the following languages. They may have translated documentation
available:
<ulink url="http://sourceforge.net/projects/bugzilla-ar/">Arabic</ulink>,
<ulink url="http://sourceforge.net/projects/bugzilla-be/">Belarusian</ulink>,
<ulink url="http://openfmi.net/projects/mozilla-bg/">Bulgarian</ulink>,
<ulink url="http://sourceforge.net/projects/bugzilla-br/">Brazilian Portuguese</ulink>,
<ulink url="http://sourceforge.net/projects/bugzilla-cn/">Chinese</ulink>,
<ulink url="http://sourceforge.net/projects/bugzilla-fr/">French</ulink>,
<ulink url="http://germzilla.ganderbay.net/">German</ulink>,
<ulink url="http://sourceforge.net/projects/bugzilla-it/">Italian</ulink>,
<ulink url="http://www.bugzilla.jp/about/jp.html">Japanese</ulink>,
<ulink url="http://sourceforge.net/projects/bugzilla-kr/">Korean</ulink>,
<ulink url="http://sourceforge.net/projects/bugzilla-ru/">Russian</ulink> and
<ulink url="http://sourceforge.net/projects/bugzilla-es/">Spanish</ulink>.
</para>
<para>
If you would like to volunteer to translate the Guide into additional
languages, please contact
<ulink url="mailto:justdave@bugzilla.org">Dave Miller</ulink>.
</para>
</section>
<section id="credits">
<title>Credits</title>
<para>
The people listed below have made enormous contributions to the
creation of this Guide, through their writing, dedicated hacking efforts,
numerous e-mail and IRC support sessions, and overall excellent
contribution to the Bugzilla community:
</para>
<!-- TODO: This is evil... there has to be a valid way to get this look -->
<variablelist>
<varlistentry>
<term>Matthew P. Barnson <email>mbarnson@sisna.com</email></term>
<listitem>
<para>for the Herculean task of pulling together the Bugzilla Guide
and shepherding it to 2.14.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Terry Weissman <email>terry@mozilla.org</email></term>
<listitem>
<para>for initially writing Bugzilla and creating the README upon
which the UNIX installation documentation is largely based.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Tara Hernandez <email>tara@tequilarists.org</email></term>
<listitem>
<para>for keeping Bugzilla development going strong after Terry left
mozilla.org and for running landfill.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Dave Lawrence <email>dkl@redhat.com</email></term>
<listitem>
<para>for providing insight into the key differences between Red
Hat's customized Bugzilla.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Dawn Endico <email>endico@mozilla.org</email></term>
<listitem>
<para>for being a hacker extraordinaire and putting up with Matthew's
incessant questions and arguments on irc.mozilla.org in #mozwebtools
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Jacob Steenhagen <email>jake@bugzilla.org</email></term>
<listitem>
<para>for taking over documentation during the 2.17 development
period.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Dave Miller <email>justdave@bugzilla.org</email></term>
<listitem>
<para>for taking over as project lead when Tara stepped down and
continually pushing for the documentation to be the best it can be.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
Thanks also go to the following people for significant contributions
to this documentation:
<simplelist type="inline">
<member>Kevin Brannen</member>
<member>Vlad Dascalu</member>
<member>Ben FrantzDale</member>
<member>Eric Hanson</member>
<member>Zach Lipton</member>
<member>Gervase Markham</member>
<member>Andrew Pearson</member>
<member>Joe Robins</member>
<member>Spencer Smith</member>
<member>Ron Teitelbaum</member>
<member>Shane Travis</member>
<member>Martin Wulffeld</member>
</simplelist>.
</para>
<para>
Also, thanks are due to the members of the
<ulink url="news://news.mozilla.org/mozilla.support.bugzilla">
mozilla.support.bugzilla</ulink>
newsgroup (and its predecessor, netscape.public.mozilla.webtools).
Without your discussions, insight, suggestions, and patches,
this could never have happened.
</para>
</section>
<!-- conventions used here (didn't want to give it a chapter of its own) -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="conventions.xml" />
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End: -->

File diff suppressed because it is too large Load Diff

View File

@@ -1,168 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<section id="conventions">
<title>Document Conventions</title>
<indexterm zone="conventions">
<primary>conventions</primary>
</indexterm>
<para>This document uses the following conventions:</para>
<informaltable frame="none">
<tgroup cols="2">
<thead>
<row>
<entry>Descriptions</entry>
<entry>Appearance</entry>
</row>
</thead>
<tbody>
<row>
<entry>Caution</entry>
<entry>
<caution>
<para>Don't run with scissors!</para>
</caution>
</entry>
</row>
<row>
<entry>Hint or Tip</entry>
<entry>
<tip>
<para>For best results... </para>
</tip>
</entry>
</row>
<row>
<entry>Note</entry>
<entry>
<note>
<para>Dear John...</para>
</note>
</entry>
</row>
<row>
<entry>Warning</entry>
<entry>
<warning>
<para>Read this or the cat gets it.</para>
</warning>
</entry>
</row>
<row>
<entry>File or directory name</entry>
<entry>
<filename>filename</filename>
</entry>
</row>
<row>
<entry>Command to be typed</entry>
<entry>
<command>command</command>
</entry>
</row>
<row>
<entry>Application name</entry>
<entry>
<application>application</application>
</entry>
</row>
<row>
<entry>
Normal user's prompt under bash shell</entry>
<entry>bash$</entry>
</row>
<row>
<entry>
Root user's prompt under bash shell</entry>
<entry>bash#</entry>
</row>
<row>
<entry>
Normal user's prompt under tcsh shell</entry>
<entry>tcsh$</entry>
</row>
<row>
<entry>Environment variables</entry>
<entry>
<envar>VARIABLE</envar>
</entry>
</row>
<row>
<entry>Term found in the glossary</entry>
<entry>
<glossterm linkend="gloss-bugzilla">Bugzilla</glossterm>
</entry>
</row>
<row>
<entry>Code example</entry>
<entry>
<programlisting><sgmltag class="starttag">para</sgmltag>
Beginning and end of paragraph
<sgmltag class="endtag">para</sgmltag></programlisting>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
This documentation is maintained in DocBook 4.1.2 XML format.
Changes are best submitted as plain text or XML diffs, attached
to a bug filed in the &bzg-bugs; component.
</para>
</section>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

View File

@@ -1,821 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<chapter id="customization">
<title>Customizing Bugzilla</title>
<section id="cust-skins">
<title>Custom Skins</title>
<para>
Bugzilla allows you to have multiple skins. These are custom CSS and possibly
also custom images for Bugzilla. To create a new custom skin, you have two
choices:
<itemizedlist>
<listitem>
<para>
Make a single CSS file, and put it in the
<filename>skins/contrib</filename> directory.
</para>
</listitem>
<listitem>
<para>
Make a directory that contains all the same CSS file
names as <filename>skins/standard/</filename>, and put
your directory in <filename>skins/contrib/</filename>.
</para>
</listitem>
</itemizedlist>
</para>
<para>
After you put the file or the directory there, make sure to run checksetup.pl
so that it can reset the file permissions correctly.
</para>
<para>
After you have installed the new skin, it will show up as an option in the
user's General Preferences. If you would like to force a particular skin on all
users, just select it in the Default Preferences and then uncheck "Enabled" on
the preference.
</para>
</section>
<section id="cust-templates">
<title>Template Customization</title>
<para>
Administrators can configure the look and feel of Bugzilla without
having to edit Perl files or face the nightmare of massive merge
conflicts when they upgrade to a newer version in the future.
</para>
<para>
Templatization also makes localized versions of Bugzilla possible,
for the first time. It's possible to have Bugzilla's UI language
determined by the user's browser. More information is available in
<xref linkend="template-http-accept"/>.
</para>
<section id="template-directory">
<title>Template Directory Structure</title>
<para>
The template directory structure starts with top level directory
named <filename>template</filename>, which contains a directory
for each installed localization. The next level defines the
language used in the templates. Bugzilla comes with English
templates, so the directory name is <filename>en</filename>,
and we will discuss <filename>template/en</filename> throughout
the documentation. Below <filename>template/en</filename> is the
<filename>default</filename> directory, which contains all the
standard templates shipped with Bugzilla.
</para>
<warning>
<para>
A directory <filename>data/templates</filename> also exists;
this is where Template Toolkit puts the compiled versions of
the templates from either the default or custom directories.
<emphasis>Do not</emphasis> directly edit the files in this
directory, or all your changes will be lost the next time
Template Toolkit recompiles the templates.
</para>
</warning>
</section>
<section id="template-method">
<title>Choosing a Customization Method</title>
<para>
If you want to edit Bugzilla's templates, the first decision
you must make is how you want to go about doing so. There are two
choices, and which you use depends mainly on the scope of your
modifications, and the method you plan to use to upgrade Bugzilla.
</para>
<para>
The first method of making customizations is to directly edit the
templates found in <filename>template/en/default</filename>.
This is probably the best way to go about it if you are going to
be upgrading Bugzilla through CVS, because if you then execute
a <command>cvs update</command>, any changes you have made will
be merged automagically with the updated versions.
</para>
<note>
<para>
If you use this method, and CVS conflicts occur during an
update, the conflicted templates (and possibly other parts
of your installation) will not work until they are resolved.
</para>
</note>
<para>
The second method is to copy the templates to be modified
into a mirrored directory structure under
<filename>template/en/custom</filename>. Templates in this
directory structure automatically override any identically-named
and identically-located templates in the
<filename>default</filename> directory.
</para>
<note>
<para>
The <filename>custom</filename> directory does not exist
at first and must be created if you want to use it.
</para>
</note>
<para>
The second method of customization should be used if you
use the overwriting method of upgrade, because otherwise
your changes will be lost. This method may also be better if
you are using the CVS method of upgrading and are going to make major
changes, because it is guaranteed that the contents of this directory
will not be touched during an upgrade, and you can then decide whether
to continue using your own templates, or make the effort to merge your
changes into the new versions by hand.
</para>
<para>
Using this method, your installation may break if incompatible
changes are made to the template interface. Such changes should
be documented in the release notes, provided you are using a
stable release of Bugzilla. If you use using unstable code, you will
need to deal with this one yourself, although if possible the changes
will be mentioned before they occur in the deprecations section of the
previous stable release's release notes.
</para>
<note>
<para>
Regardless of which method you choose, it is recommended that
you run <command>./checksetup.pl</command> after creating or
editing any templates in the <filename>template/en/default</filename>
directory, and after editing any templates in the
<filename>custom</filename> directory.
</para>
</note>
<warning>
<para>
It is <emphasis>required</emphasis> that you run
<command>./checksetup.pl</command> after creating a new
template in the <filename>custom</filename> directory. Failure
to do so will raise an incomprehensible error message.
</para>
</warning>
</section>
<section id="template-edit">
<title>How To Edit Templates</title>
<note>
<para>
If you are making template changes that you intend on submitting back
for inclusion in standard Bugzilla, you should read the relevant
sections of the
<ulink url="http://www.bugzilla.org/docs/developer.html">Developers'
Guide</ulink>.
</para>
</note>
<para>
The syntax of the Template Toolkit language is beyond the scope of
this guide. It's reasonably easy to pick up by looking at the current
templates; or, you can read the manual, available on the
<ulink url="http://www.template-toolkit.org">Template Toolkit home
page</ulink>.
</para>
<para>
One thing you should take particular care about is the need
to properly HTML filter data that has been passed into the template.
This means that if the data can possibly contain special HTML characters
such as &lt;, and the data was not intended to be HTML, they need to be
converted to entity form, i.e. &amp;lt;. You use the 'html' filter in the
Template Toolkit to do this. If you forget, you may open up
your installation to cross-site scripting attacks.
</para>
<para>
Also note that Bugzilla adds a few filters of its own, that are not
in standard Template Toolkit. In particular, the 'url_quote' filter
can convert characters that are illegal or have special meaning in URLs,
such as &amp;, to the encoded form, i.e. %26. This actually encodes most
characters (but not the common ones such as letters and numbers and so
on), including the HTML-special characters, so there's never a need to
HTML filter afterwards.
</para>
<para>
Editing templates is a good way of doing a <quote>poor man's custom
fields</quote>.
For example, if you don't use the Status Whiteboard, but want to have
a free-form text entry box for <quote>Build Identifier</quote>,
then you can just
edit the templates to change the field labels. It's still be called
status_whiteboard internally, but your users don't need to know that.
</para>
</section>
<section id="template-formats">
<title>Template Formats and Types</title>
<para>
Some CGI's have the ability to use more than one template. For example,
<filename>buglist.cgi</filename> can output itself as RDF, or as two
formats of HTML (complex and simple). The mechanism that provides this
feature is extensible.
</para>
<para>
Bugzilla can support different types of output, which again can have
multiple formats. In order to request a certain type, you can append
the &amp;ctype=&lt;contenttype&gt; (such as rdf or html) to the
<filename>&lt;cginame&gt;.cgi</filename> URL. If you would like to
retrieve a certain format, you can use the &amp;format=&lt;format&gt;
(such as simple or complex) in the URL.
</para>
<para>
To see if a CGI supports multiple output formats and types, grep the
CGI for <quote>get_format</quote>. If it's not present, adding
multiple format/type support isn't too hard - see how it's done in
other CGIs, e.g. config.cgi.
</para>
<para>
To make a new format template for a CGI which supports this,
open a current template for
that CGI and take note of the INTERFACE comment (if present.) This
comment defines what variables are passed into this template. If
there isn't one, I'm afraid you'll have to read the template and
the code to find out what information you get.
</para>
<para>
Write your template in whatever markup or text style is appropriate.
</para>
<para>
You now need to decide what content type you want your template
served as. The content types are defined in the
<filename>Bugzilla/Constants.pm</filename> file in the
<filename>contenttypes</filename>
constant. If your content type is not there, add it. Remember
the three- or four-letter tag assigned to your content type.
This tag will be part of the template filename.
</para>
<note>
<para>
After adding or changing a content type, it's suitable to edit
<filename>Bugzilla/Constants.pm</filename> in order to reflect
the changes. Also, the file should be kept up to date after an
upgrade if content types have been customized in the past.
</para>
</note>
<para>
Save the template as <filename>&lt;stubname&gt;-&lt;formatname&gt;.&lt;contenttypetag&gt;.tmpl</filename>.
Try out the template by calling the CGI as
<filename>&lt;cginame&gt;.cgi?format=&lt;formatname&gt;&amp;ctype=&lt;type&gt;</filename> .
</para>
</section>
<section id="template-specific">
<title>Particular Templates</title>
<para>
There are a few templates you may be particularly interested in
customizing for your installation.
</para>
<para>
<command>index.html.tmpl</command>:
This is the Bugzilla front page.
</para>
<para>
<command>global/header.html.tmpl</command>:
This defines the header that goes on all Bugzilla pages.
The header includes the banner, which is what appears to users
and is probably what you want to edit instead. However the
header also includes the HTML HEAD section, so you could for
example add a stylesheet or META tag by editing the header.
</para>
<para>
<command>global/banner.html.tmpl</command>:
This contains the <quote>banner</quote>, the part of the header
that appears
at the top of all Bugzilla pages. The default banner is reasonably
barren, so you'll probably want to customize this to give your
installation a distinctive look and feel. It is recommended you
preserve the Bugzilla version number in some form so the version
you are running can be determined, and users know what docs to read.
</para>
<para>
<command>global/footer.html.tmpl</command>:
This defines the footer that goes on all Bugzilla pages. Editing
this is another way to quickly get a distinctive look and feel for
your Bugzilla installation.
</para>
<para>
<command>global/variables.none.tmpl</command>:
This defines a list of terms that may be changed in order to
<quote>brand</quote> the Bugzilla instance In this way, terms
like <quote>bugs</quote> can be replaced with <quote>issues</quote>
across the whole Bugzilla installation. The name
<quote>Bugzilla</quote> and other words can be customized as well.
</para>
<para>
<command>list/table.html.tmpl</command>:
This template controls the appearance of the bug lists created
by Bugzilla. Editing this template allows per-column control of
the width and title of a column, the maximum display length of
each entry, and the wrap behaviour of long entries.
For long bug lists, Bugzilla inserts a 'break' every 100 bugs by
default; this behaviour is also controlled by this template, and
that value can be modified here.
</para>
<para>
<command>bug/create/user-message.html.tmpl</command>:
This is a message that appears near the top of the bug reporting page.
By modifying this, you can tell your users how they should report
bugs.
</para>
<para>
<command>bug/process/midair.html.tmpl</command>:
This is the page used if two people submit simultaneous changes to the
same bug. The second person to submit their changes will get this page
to tell them what the first person did, and ask if they wish to
overwrite those changes or go back and revisit the bug. The default
title and header on this page read "Mid-air collision detected!" If
you work in the aviation industry, or other environment where this
might be found offensive (yes, we have true stories of this happening)
you'll want to change this to something more appropriate for your
environment.
</para>
<para>
<command>bug/create/create.html.tmpl</command> and
<command>bug/create/comment.txt.tmpl</command>:
You may not wish to go to the effort of creating custom fields in
Bugzilla, yet you want to make sure that each bug report contains
a number of pieces of important information for which there is not
a special field. The bug entry system has been designed in an
extensible fashion to enable you to add arbitrary HTML widgets,
such as drop-down lists or textboxes, to the bug entry page
and have their values appear formatted in the initial comment.
A hidden field that indicates the format should be added inside
the form in order to make the template functional. Its value should
be the suffix of the template filename. For example, if the file
is called <filename>create-cust.html.tmpl</filename>, then
<programlisting>&lt;input type="hidden" name="format" value="cust"&gt;</programlisting>
should be used inside the form.
</para>
<para>
An example of this is the mozilla.org
<ulink url="http://landfill.bugzilla.org/bugzilla-tip/enter_bug.cgi?product=WorldControl&amp;format=guided">guided
bug submission form</ulink>. The code for this comes with the Bugzilla
distribution as an example for you to copy. It can be found in the
files
<filename>create-guided.html.tmpl</filename> and
<filename>comment-guided.html.tmpl</filename>.
</para>
<para>
So to use this feature, create a custom template for
<filename>enter_bug.cgi</filename>. The default template, on which you
could base it, is
<filename>custom/bug/create/create.html.tmpl</filename>.
Call it <filename>create-&lt;formatname&gt;.html.tmpl</filename>, and
in it, add widgets for each piece of information you'd like
collected - such as a build number, or set of steps to reproduce.
</para>
<para>
Then, create a template like
<filename>custom/bug/create/comment.txt.tmpl</filename>, and call it
<filename>comment-&lt;formatname&gt;.txt.tmpl</filename>. This
template should reference the form fields you have created using
the syntax <filename>[% form.&lt;fieldname&gt; %]</filename>. When a
bug report is
submitted, the initial comment attached to the bug report will be
formatted according to the layout of this template.
</para>
<para>
For example, if your custom enter_bug template had a field
<programlisting>&lt;input type="text" name="buildid" size="30"&gt;</programlisting>
and then your comment.txt.tmpl had
<programlisting>BuildID: [% form.buildid %]</programlisting>
then something like
<programlisting>BuildID: 20020303</programlisting>
would appear in the initial comment.
</para>
</section>
<section id="template-http-accept">
<title>Configuring Bugzilla to Detect the User's Language</title>
<para>Bugzilla honours the user's Accept: HTTP header. You can install
templates in other languages, and Bugzilla will pick the most appropriate
according to a priority order defined by you. Many
language templates can be obtained from <ulink
url="http://www.bugzilla.org/download.html#localizations"/>. Instructions
for submitting new languages are also available from that location.
</para>
</section>
</section>
<section id="cust-hooks">
<title>The Bugzilla Extension Mechanism</title>
<warning>
<para>
Note that the below paths are inconsistent and confusing. They will
likely be changed in Bugzilla 4.0.
</para>
</warning>
<para>
Extensions are a way for extensions to Bugzilla to insert code
into the standard Bugzilla templates and source files
without modifying these files themselves. The extension mechanism
defines a consistent API for extending the standard templates and source files
in a way that cleanly separates standard code from extension code.
Hooks reduce merge conflicts and make it easier to write extensions that work
across multiple versions of Bugzilla, making upgrading a Bugzilla installation
with installed extensions easier. Furthermore, they make it easy to install
and remove extensions as each extension is nothing more than a
simple directory structure.
</para>
<para>
There are two main types of hooks: code hooks and template hooks. Code
hooks allow extensions to invoke code at specific points in various
source files, while template hooks allow extensions to add elements to
the Bugzilla user interface.
</para>
<para>
A hook is just a named place in a standard source or template file
where extension source code or template files for that hook get processed.
Each extension has a corresponding directory in the Bugzilla directory
tree (<filename>BUGZILLA_ROOT/extensions/extension_name</filename>). Hooking
an extension source file or template to a hook is as simple as putting
the extension file into extension's template or code directory.
When Bugzilla processes the source file or template and reaches the hook,
it will process all extension files in the hook's directory.
The hooks themselves can be added into any source file or standard template
upon request by extension authors.
</para>
<para>
To use hooks to extend Bugzilla, first make sure there is
a hook at the appropriate place within the source file or template you
want to extend. The exact appearance of a hook depends on if the hook
is a code hook or a template hook.
</para>
<para>
Code hooks appear in Bugzilla source files as a single method call
in the format <literal role="code">Bugzilla::Hook->process("<varname>name</varname>");</literal>.
For instance, <filename>enter_bug.cgi</filename> may invoke the hook
"<varname>enter_bug-entrydefaultvars</varname>". Thus, a source file at
<filename>BUGZILLA_ROOT/extensions/EXTENSION_NAME/code/enter_bug-entrydefaultvars.pl</filename>
will be automatically invoked when the code hook is reached.
</para>
<para>
Template hooks appear in the standard Bugzilla templates as a
single directive in the format
<literal role="code">[% Hook.process("<varname>name</varname>") %]</literal>,
where <varname>name</varname> is the unique name of the hook.
</para>
<para>
If you aren't sure what you want to extend or just want to browse the
available hooks, either use your favorite multi-file search
tool (e.g. <command>grep</command>) to search the standard templates
for occurrences of <methodname>Hook.process</methodname> or the source
files for occurrences of <methodname>Bugzilla::Hook::process</methodname>.
</para>
<para>
If there is no hook at the appropriate place within the Bugzilla
source file or template you want to extend,
<ulink url="http://bugzilla.mozilla.org/enter_bug.cgi?product=Bugzilla&amp;component=User%20Interface">file
a bug requesting one</ulink>, specifying:
</para>
<simplelist>
<member>the source or template file for which you are
requesting a hook;</member>
<member>
where in the file you would like the hook to be placed
(line number/position for latest version of the file in CVS
or description of location);
</member>
<member>the purpose of the hook;</member>
<member>a link to information about your extension, if any.</member>
</simplelist>
<para>
The Bugzilla reviewers will promptly review each hook request,
name the hook, add it to the template or source file, and check
the new version of the template into CVS.
</para>
<para>
You may optionally attach a patch to the bug which implements the hook
and check it in yourself after receiving approval from a Bugzilla
reviewer. The developers may suggest changes to the location of the
hook based on their analysis of your needs or so the hook can satisfy
the needs of multiple extensions, but the process of getting hooks
approved and checked in is not as stringent as the process for general
changes to Bugzilla, and any extension, whether released or still in
development, can have hooks added to meet their needs.
</para>
<para>
After making sure the hook you need exists (or getting it added if not),
add your extension to the directory within the Bugzilla
extensions tree corresponding to the hook.
</para>
<para>
That's it! Now, when the source file or template containing the hook
is processed, your extension file will be processed at the point
where the hook appears.
</para>
<para>
For example, let's say you have an extension named Projman that adds
project management capabilities to Bugzilla. Projman has an
administration interface <filename>edit-projects.cgi</filename>,
and you want to add a link to it into the navigation bar at the bottom
of every Bugzilla page for those users who are authorized
to administer projects.
</para>
<para>
The navigation bar is generated by the template file
<filename>useful-links.html.tmpl</filename>, which is located in
the <filename>global/</filename> subdirectory on the standard Bugzilla
template path
<filename>BUGZILLA_ROOT/template/en/default/</filename>.
Looking in <filename>useful-links.html.tmpl</filename>, you find
the following hook at the end of the list of standard Bugzilla
administration links:
</para>
<programlisting><![CDATA[...
[% ', <a href="editkeywords.cgi">keywords</a>'
IF user.groups.editkeywords %]
[% Hook.process("edit") %]
...]]></programlisting>
<para>
The corresponding extension file for this hook is
<filename>BUGZILLA_ROOT/extensions/projman/template/en/global/useful-links-edit.html.tmpl</filename>.
You then create that template file and add the following constant:
</para>
<programlisting><![CDATA[...[% ', <a href="edit-projects.cgi">projects</a>' IF user.groups.projman_admins %]]]></programlisting>
<para>
Voila! The link now appears after the other administration links in the
navigation bar for users in the <literal>projman_admins</literal> group.
</para>
<para>
Now, let us say your extension adds a custom "project_manager" field
to enter_bug.cgi. You want to modify the CGI script to set the default
project manager to be productname@company.com. Looking at
<filename>enter_bug.cgi</filename>, you see the enter_bug-entrydefaultvars
hook near the bottom of the file before the default form values are set.
The corresponding extension source file for this hook is located at
<filename>BUGZILLA_ROOT/extensions/projman/code/enter_bug-entrydefaultvars.pl</filename>.
You then create that file and add the following:
</para>
<programlisting>$default{'project_manager'} = $product.'@company.com';</programlisting>
<para>
This code will be invoked whenever enter_bug.cgi is executed.
Assuming that the rest of the customization was completed (e.g. the
custom field was added to the enter_bug template and the required hooks
were used in process_bug.cgi), the new field will now have this
default value.
</para>
<para>
Notes:
</para>
<itemizedlist>
<listitem>
<para>
If your extension includes entirely new templates in addition to
extensions of standard templates, it should store those new
templates in its
<filename>BUGZILLA_ROOT/extensions/template/en/</filename>
directory. Extension template directories, like the
<filename>default/</filename> and <filename>custom/</filename>
directories, are part of the template search path, so putting templates
there enables them to be found by the template processor.
</para>
<para>
The template processor looks for templates first in the
<filename>custom/</filename> directory (i.e. templates added by the
specific installation), then in the <filename>extensions/</filename>
directory (i.e. templates added by extensions), and finally in the
<filename>default/</filename> directory (i.e. the standard Bugzilla
templates). Thus, installation-specific templates override both
default and extension templates.
</para>
</listitem>
<listitem>
<para>
If you are looking to customize Bugzilla, you can also take advantage
of template hooks. To do so, create a directory in
<filename>BUGZILLA_ROOT/template/en/custom/hook/</filename>
that corresponds to the hook you wish to use, then place your
customization templates into those directories. For example,
if you wanted to use the hook "end" in
<filename>global/useful-links.html.tmpl</filename>, you would
create the directory <filename>BUGZILLA_ROOT/template/en/custom/hook/
global/useful-links.html.tmpl/end/</filename> and add your customization
template to this directory.
</para>
<para>
Obviously this method of customizing Bugzilla only lets you add code
to the standard source files and templates; you cannot change the
existing code. Nevertheless, for those customizations that only add
code, this method can reduce conflicts when merging changes,
making upgrading your customized Bugzilla installation easier.
</para>
</listitem>
</itemizedlist>
</section>
<section id="cust-change-permissions">
<title>Customizing Who Can Change What</title>
<warning>
<para>
This feature should be considered experimental; the Bugzilla code you
will be changing is not stable, and could change or move between
versions. Be aware that if you make modifications as outlined here,
you may have
to re-make them or port them if Bugzilla changes internally between
versions, and you upgrade.
</para>
</warning>
<para>
Companies often have rules about which employees, or classes of employees,
are allowed to change certain things in the bug system. For example,
only the bug's designated QA Contact may be allowed to VERIFY the bug.
Bugzilla has been
designed to make it easy for you to write your own custom rules to define
who is allowed to make what sorts of value transition.
</para>
<para>
By default, assignees, QA owners and users
with <emphasis>editbugs</emphasis> privileges can edit all fields of bugs,
except group restrictions (unless they are members of the groups they
are trying to change). Bug reporters also have the ability to edit some
fields, but in a more restrictive manner. Other users, without
<emphasis>editbugs</emphasis> privileges, can not edit
bugs, except to comment and add themselves to the CC list.
</para>
<para>
For maximum flexibility, customizing this means editing Bugzilla's Perl
code. This gives the administrator complete control over exactly who is
allowed to do what. The relevant method is called
<filename>check_can_change_field()</filename>,
and is found in <filename>Bug.pm</filename> in your
Bugzilla/ directory. If you open that file and search for
<quote>sub check_can_change_field</quote>, you'll find it.
</para>
<para>
This function has been carefully commented to allow you to see exactly
how it works, and give you an idea of how to make changes to it.
Certain marked sections should not be changed - these are
the <quote>plumbing</quote> which makes the rest of the function work.
In between those sections, you'll find snippets of code like:
<programlisting> # Allow the assignee to change anything.
if ($ownerid eq $whoid) {
return 1;
}</programlisting>
It's fairly obvious what this piece of code does.
</para>
<para>
So, how does one go about changing this function? Well, simple changes
can be made just by removing pieces - for example, if you wanted to
prevent any user adding a comment to a bug, just remove the lines marked
<quote>Allow anyone to change comments.</quote> If you don't want the
Reporter to have any special rights on bugs they have filed, just
remove the entire section that deals with the Reporter.
</para>
<para>
More complex customizations are not much harder. Basically, you add
a check in the right place in the function, i.e. after all the variables
you are using have been set up. So, don't look at $ownerid before
$ownerid has been obtained from the database. You can either add a
positive check, which returns 1 (allow) if certain conditions are true,
or a negative check, which returns 0 (deny.) E.g.:
<programlisting> if ($field eq "qacontact") {
if (Bugzilla->user->groups("quality_assurance")) {
return 1;
}
else {
return 0;
}
}</programlisting>
This says that only users in the group "quality_assurance" can change
the QA Contact field of a bug.
</para>
<para>
Getting more weird:
<programlisting><![CDATA[ if (($field eq "priority") &&
(Bugzilla->user->email =~ /.*\@example\.com$/))
{
if ($oldvalue eq "P1") {
return 1;
}
else {
return 0;
}
}]]></programlisting>
This says that if the user is trying to change the priority field,
and their email address is @example.com, they can only do so if the
old value of the field was "P1". Not very useful, but illustrative.
</para>
<warning>
<para>
If you are modifying <filename>process_bug.cgi</filename> in any
way, do not change the code that is bounded by DO_NOT_CHANGE blocks.
Doing so could compromise security, or cause your installation to
stop working entirely.
</para>
</warning>
<para>
For a list of possible field names, look at the bugs table in the
database. If you need help writing custom rules for your organization,
ask in the newsgroup.
</para>
</section>
<!-- Integrating Bugzilla with Third-Party Tools -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="integration.xml" />
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

View File

@@ -1,449 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<appendix id="gfdl">
<title>GNU Free Documentation License</title>
<!-- - GNU Project - Free Software Foundation (FSF) -->
<!-- LINK REV="made" HREF="mailto:webmasters@gnu.org" -->
<!-- section>
<title>GNU Free Documentation License</title -->
<para>Version 1.1, March 2000</para>
<blockquote>
<para>Copyright (C) 2000 Free Software Foundation, Inc. 59 Temple Place,
Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and
distribute verbatim copies of this license document, but changing it is
not allowed.</para>
</blockquote>
<section label="0" id="gfdl-0">
<title>Preamble</title>
<para>The purpose of this License is to make a manual, textbook, or other
written document "free" in the sense of freedom: to assure everyone the
effective freedom to copy and redistribute it, with or without modifying
it, either commercially or noncommercially. Secondarily, this License
preserves for the author and publisher a way to get credit for their
work, while not being considered responsible for modifications made by
others.</para>
<para>This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense. It
complements the GNU General Public License, which is a copyleft license
designed for free software.</para>
<para>We have designed this License in order to use it for manuals for
free software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does. But this License is not limited to software manuals; it
can be used for any textual work, regardless of subject matter or whether
it is published as a printed book. We recommend this License principally
for works whose purpose is instruction or reference.</para>
</section>
<section label="1" id="gfdl-1">
<title>Applicability and Definition</title>
<para>This License applies to any manual or other work that contains a
notice placed by the copyright holder saying it can be distributed under
the terms of this License. The "Document", below, refers to any such
manual or work. Any member of the public is a licensee, and is addressed
as "you".</para>
<para>A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.</para>
<para>A "Secondary Section" is a named appendix or a front-matter section
of the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject. (For example, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.) The relationship could be a matter of historical connection
with the subject or with related matters, or of legal, commercial,
philosophical, ethical or political position regarding them.</para>
<para>The "Invariant Sections" are certain Secondary Sections whose
titles are designated, as being those of Invariant Sections, in the
notice that says that the Document is released under this License.</para>
<para>The "Cover Texts" are certain short passages of text that are
listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says
that the Document is released under this License.</para>
<para>A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the general
public, whose contents can be viewed and edited directly and
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or for
automatic translation to a variety of formats suitable for input to text
formatters. A copy made in an otherwise Transparent file format whose
markup has been designed to thwart or discourage subsequent modification
by readers is not Transparent. A copy that is not "Transparent" is called
"Opaque".</para>
<para>Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML or
XML using a publicly available DTD, and standard-conforming simple HTML
designed for human modification. Opaque formats include PostScript, PDF,
proprietary formats that can be read and edited only by proprietary word
processors, SGML or XML for which the DTD and/or processing tools are not
generally available, and the machine-generated HTML produced by some word
processors for output purposes only.</para>
<para>The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in formats
which do not have any title page as such, "Title Page" means the text
near the most prominent appearance of the work's title, preceding the
beginning of the body of the text.</para>
</section>
<section label="2" id="gfdl-2">
<title>Verbatim Copying</title>
<para>You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies to
the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License. You may not use technical
measures to obstruct or control the reading or further copying of the
copies you make or distribute. However, you may accept compensation in
exchange for copies. If you distribute a large enough number of copies
you must also follow the conditions in section 3.</para>
<para>You may also lend copies, under the same conditions stated above,
and you may publicly display copies.</para>
</section>
<section label="3" id="gfdl-3">
<title>Copying in Quantity</title>
<para>If you publish printed copies of the Document numbering more than
100, and the Document's license notice requires Cover Texts, you must
enclose the copies in covers that carry, clearly and legibly, all these
Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts
on the back cover. Both covers must also clearly and legibly identify you
as the publisher of these copies. The front cover must present the full
title with all words of the title equally prominent and visible. You may
add other material on the covers in addition. Copying with changes
limited to the covers, as long as they preserve the title of the Document
and satisfy these conditions, can be treated as verbatim copying in other
respects.</para>
<para>If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit reasonably)
on the actual cover, and continue the rest onto adjacent pages.</para>
<para>If you publish or distribute Opaque copies of the Document
numbering more than 100, you must either include a machine-readable
Transparent copy along with each Opaque copy, or state in or with each
Opaque copy a publicly-accessible computer-network location containing a
complete Transparent copy of the Document, free of added material, which
the general network-using public has access to download anonymously at no
charge using public-standard network protocols. If you use the latter
option, you must take reasonably prudent steps, when you begin
distribution of Opaque copies in quantity, to ensure that this
Transparent copy will remain thus accessible at the stated location until
at least one year after the last time you distribute an Opaque copy
(directly or through your agents or retailers) of that edition to the
public.</para>
<para>It is requested, but not required, that you contact the authors of
the Document well before redistributing any large number of copies, to
give them a chance to provide you with an updated version of the
Document.</para>
</section>
<section label="4" id="gfdl-4">
<title>Modifications</title>
<para>You may copy and distribute a Modified Version of the Document
under the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution and
modification of the Modified Version to whoever possesses a copy of it.
In addition, you must do these things in the Modified Version:</para>
<orderedlist numeration="upperalpha">
<listitem>
<para>Use in the Title Page (and on the covers, if any) a title
distinct from that of the Document, and from those of previous
versions (which should, if there were any, be listed in the History
section of the Document). You may use the same title as a previous
version if the original publisher of that version gives
permission.</para>
</listitem>
<listitem>
<para>List on the Title Page, as authors, one or more persons or
entities responsible for authorship of the modifications in the
Modified Version, together with at least five of the principal
authors of the Document (all of its principal authors, if it has less
than five).</para>
</listitem>
<listitem>
<para>State on the Title page the name of the publisher of the
Modified Version, as the publisher.</para>
</listitem>
<listitem>
<para>Preserve all the copyright notices of the Document.</para>
</listitem>
<listitem>
<para>Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.</para>
</listitem>
<listitem>
<para>Include, immediately after the copyright notices, a license
notice giving the public permission to use the Modified Version under
the terms of this License, in the form shown in the Addendum
below.</para>
</listitem>
<listitem>
<para>Preserve in that license notice the full lists of Invariant
Sections and required Cover Texts given in the Document's license
notice.</para>
</listitem>
<listitem>
<para>Include an unaltered copy of this License.</para>
</listitem>
<listitem>
<para>Preserve the section entitled "History", and its title, and add
to it an item stating at least the title, year, new authors, and
publisher of the Modified Version as given on the Title Page. If
there is no section entitled "History" in the Document, create one
stating the title, year, authors, and publisher of the Document as
given on its Title Page, then add an item describing the Modified
Version as stated in the previous sentence.</para>
</listitem>
<listitem>
<para>Preserve the network location, if any, given in the Document
for public access to a Transparent copy of the Document, and likewise
the network locations given in the Document for previous versions it
was based on. These may be placed in the "History" section. You may
omit a network location for a work that was published at least four
years before the Document itself, or if the original publisher of the
version it refers to gives permission.</para>
</listitem>
<listitem>
<para>In any section entitled "Acknowledgements" or "Dedications",
preserve the section's title, and preserve in the section all the
substance and tone of each of the contributor acknowledgements and/or
dedications given therein.</para>
</listitem>
<listitem>
<para>Preserve all the Invariant Sections of the Document, unaltered
in their text and in their titles. Section numbers or the equivalent
are not considered part of the section titles.</para>
</listitem>
<listitem>
<para>Delete any section entitled "Endorsements". Such a section may
not be included in the Modified Version.</para>
</listitem>
<listitem>
<para>Do not retitle any existing section as "Endorsements" or to
conflict in title with any Invariant Section.</para>
</listitem>
</orderedlist>
<para>If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all of
these sections as invariant. To do this, add their titles to the list of
Invariant Sections in the Modified Version's license notice. These titles
must be distinct from any other section titles.</para>
<para>You may add a section entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various parties--for
example, statements of peer review or that the text has been approved by
an organization as the authoritative definition of a standard.</para>
<para>You may add a passage of up to five words as a Front-Cover Text,
and a passage of up to 25 words as a Back-Cover Text, to the end of the
list of Cover Texts in the Modified Version. Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or through
arrangements made by) any one entity. If the Document already includes a
cover text for the same cover, previously added by you or by arrangement
made by the same entity you are acting on behalf of, you may not add
another; but you may replace the old one, on explicit permission from the
previous publisher that added the old one.</para>
<para>The author(s) and publisher(s) of the Document do not by this
License give permission to use their names for publicity for or to assert
or imply endorsement of any Modified Version.</para>
</section>
<section label="5" id="gfdl-5">
<title>Combining Documents</title>
<para>You may combine the Document with other documents released under
this License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and list
them all as Invariant Sections of your combined work in its license
notice.</para>
<para>The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single copy.
If there are multiple Invariant Sections with the same name but different
contents, make the title of each such section unique by adding at the end
of it, in parentheses, the name of the original author or publisher of
that section if known, or else a unique number. Make the same adjustment
to the section titles in the list of Invariant Sections in the license
notice of the combined work.</para>
<para>In the combination, you must combine any sections entitled
"History" in the various original documents, forming one section entitled
"History"; likewise combine any sections entitled "Acknowledgements", and
any sections entitled "Dedications". You must delete all sections
entitled "Endorsements."</para>
</section>
<section label="6" id="gfdl-6">
<title>Collections of Documents</title>
<para>You may make a collection consisting of the Document and other
documents released under this License, and replace the individual copies
of this License in the various documents with a single copy that is
included in the collection, provided that you follow the rules of this
License for verbatim copying of each of the documents in all other
respects.</para>
<para>You may extract a single document from such a collection, and
distribute it individually under this License, provided you insert a copy
of this License into the extracted document, and follow this License in
all other respects regarding verbatim copying of that document.</para>
</section>
<section label="7" id="gfdl-7">
<title>Aggregation with Independent Works</title>
<para>A compilation of the Document or its derivatives with other
separate and independent documents or works, in or on a volume of a
storage or distribution medium, does not as a whole count as a Modified
Version of the Document, provided no compilation copyright is claimed for
the compilation. Such a compilation is called an "aggregate", and this
License does not apply to the other self-contained works thus compiled
with the Document, on account of their being thus compiled, if they are
not themselves derivative works of the Document.</para>
<para>If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one quarter of
the entire aggregate, the Document's Cover Texts may be placed on covers
that surround only the Document within the aggregate. Otherwise they must
appear on covers around the whole aggregate.</para>
</section>
<section label="8" id="gfdl-8">
<title>Translation</title>
<para>Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include translations
of some or all Invariant Sections in addition to the original versions of
these Invariant Sections. You may include a translation of this License
provided that you also include the original English version of this
License. In case of a disagreement between the translation and the
original English version of this License, the original English version
will prevail.</para>
</section>
<section label="9" id="gfdl-9">
<title>Termination</title>
<para>You may not copy, modify, sublicense, or distribute the Document
except as expressly provided for under this License. Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License. However, parties
who have received copies, or rights, from you under this License will not
have their licenses terminated so long as such parties remain in full
compliance.</para>
</section>
<section label="10" id="gfdl-10">
<title>Future Revisions of this License</title>
<para>The Free Software Foundation may publish new, revised versions of
the GNU Free Documentation License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in
detail to address new problems or concerns. See
<ulink url="http://www.gnu.org/copyleft/"/>.</para>
<para>Each version of the License is given a distinguishing version
number. If the Document specifies that a particular numbered version of
this License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or of
any later version that has been published (not as a draft) by the Free
Software Foundation. If the Document does not specify a version number of
this License, you may choose any version ever published (not as a draft)
by the Free Software Foundation.</para>
</section>
<section label="" id="gfdl-howto">
<title>How to use this License for your documents</title>
<para>To use this License in a document you have written, include a copy
of the License in the document and put the following copyright and
license notices just after the title page:</para>
<blockquote>
<para>Copyright (c) YEAR YOUR NAME. Permission is granted to copy,
distribute and/or modify this document under the terms of the GNU Free
Documentation License, Version 1.1 or any later version published by
the Free Software Foundation; with the Invariant Sections being LIST
THEIR TITLES, with the Front-Cover Texts being LIST, and with the
Back-Cover Texts being LIST. A copy of the license is included in the
section entitled "GNU Free Documentation License".</para>
</blockquote>
<para>If you have no Invariant Sections, write "with no Invariant
Sections" instead of saying which ones are invariant. If you have no
Front-Cover Texts, write "no Front-Cover Texts" instead of "Front-Cover
Texts being LIST"; likewise for Back-Cover Texts.</para>
<para>If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of free
software license, such as the GNU General Public License, to permit their
use in free software.</para>
</section>
</appendix>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

View File

@@ -1,555 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<glossary id="glossary">
<glossdiv>
<title>0-9, high ascii</title>
<glossentry id="gloss-htaccess">
<glossterm>.htaccess</glossterm>
<glossdef>
<para>Apache web server, and other NCSA-compliant web servers,
observe the convention of using files in directories called
<filename>.htaccess</filename>
to restrict access to certain files. In Bugzilla, they are used
to keep secret files which would otherwise
compromise your installation - e.g. the
<filename>localconfig</filename>
file contains the password to your database.
curious.</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-a">
<title>A</title>
<glossentry id="gloss-apache">
<glossterm>Apache</glossterm>
<glossdef>
<para>In this context, Apache is the web server most commonly used
for serving up Bugzilla
pages. Contrary to popular belief, the apache web server has nothing
to do with the ancient and noble Native American tribe, but instead
derived its name from the fact that it was
<quote>a patchy</quote>
version of the original
<acronym>NCSA</acronym>
world-wide-web server.</para>
<variablelist>
<title>Useful Directives when configuring Bugzilla</title>
<varlistentry>
<term><computeroutput><ulink url="http://httpd.apache.org/docs-2.0/mod/core.html#addhandler">AddHandler</ulink></computeroutput></term>
<listitem>
<para>Tell Apache that it's OK to run CGI scripts.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><computeroutput><ulink url="http://httpd.apache.org/docs-2.0/mod/core.html#allowoverride">AllowOverride</ulink></computeroutput></term>
<term><computeroutput><ulink url="http://httpd.apache.org/docs-2.0/mod/core.html#options">Options</ulink></computeroutput></term>
<listitem>
<para>These directives are used to tell Apache many things about
the directory they apply to. For Bugzilla's purposes, we need
them to allow script execution and <filename>.htaccess</filename>
overrides.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><computeroutput><ulink url="http://httpd.apache.org/docs-2.0/mod/mod_dir.html#directoryindex">DirectoryIndex</ulink></computeroutput></term>
<listitem>
<para>Used to tell Apache what files are indexes. If you can
not add <filename>index.cgi</filename> to the list of valid files,
you'll need to set <computeroutput>$index_html</computeroutput> to
1 in <filename>localconfig</filename> so
<command>./checksetup.pl</command> will create an
<filename>index.html</filename> that redirects to
<filename>index.cgi</filename>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><computeroutput><ulink url="http://httpd.apache.org/docs-2.0/mod/core.html#scriptinterpretersource">ScriptInterpreterSource</ulink></computeroutput></term>
<listitem>
<para>Used when running Apache on windows so the shebang line
doesn't have to be changed in every Bugzilla script.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>For more information about how to configure Apache for Bugzilla,
see <xref linkend="http-apache"/>.
</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-b">
<title>B</title>
<glossentry>
<glossterm>Bug</glossterm>
<glossdef>
<para>A
<quote>bug</quote>
in Bugzilla refers to an issue entered into the database which has an
associated number, assignments, comments, etc. Some also refer to a
<quote>tickets</quote>
or
<quote>issues</quote>;
in the context of Bugzilla, they are synonymous.</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm>Bug Number</glossterm>
<glossdef>
<para>Each Bugzilla bug is assigned a number that uniquely identifies
that bug. The bug associated with a bug number can be pulled up via a
query, or easily from the very front page by typing the number in the
"Find" box.</para>
</glossdef>
</glossentry>
<glossentry id="gloss-bugzilla">
<glossterm>Bugzilla</glossterm>
<glossdef>
<para>Bugzilla is the world-leading free software bug tracking system.
</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-c">
<title>C</title>
<glossentry id="gloss-cgi">
<glossterm>Common Gateway Interface</glossterm>
<acronym>CGI</acronym>
<glossdef>
<para><acronym>CGI</acronym> is an acronym for Common Gateway Interface. This is
a standard for interfacing an external application with a web server. Bugzilla
is an example of a <acronym>CGI</acronym> application.
</para>
</glossdef>
</glossentry>
<glossentry id="gloss-component">
<glossterm>Component</glossterm>
<glossdef>
<para>A Component is a subsection of a Product. It should be a narrow
category, tailored to your organization. All Products must contain at
least one Component (and, as a matter of fact, creating a Product
with no Components will create an error in Bugzilla).</para>
</glossdef>
</glossentry>
<glossentry id="gloss-cpan">
<glossterm>Comprehensive Perl Archive Network</glossterm>
<acronym>CPAN</acronym>
<!-- TODO: Rewrite def for CPAN -->
<glossdef>
<para>
<acronym>CPAN</acronym>
stands for the
<quote>Comprehensive Perl Archive Network</quote>.
CPAN maintains a large number of extremely useful
<glossterm>Perl</glossterm>
modules - encapsulated chunks of code for performing a
particular task.</para>
</glossdef>
</glossentry>
<glossentry id="gloss-contrib">
<glossterm><filename class="directory">contrib</filename></glossterm>
<glossdef>
<para>The <filename class="directory">contrib</filename> directory is
a location to put scripts that have been contributed to Bugzilla but
are not a part of the official distribution. These scripts are written
by third parties and may be in languages other than perl. For those
that are in perl, there may be additional modules or other requirements
than those of the official distribution.
<note>
<para>Scripts in the <filename class="directory">contrib</filename>
directory are not officially supported by the Bugzilla team and may
break in between versions.
</para>
</note>
</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-d">
<title>D</title>
<glossentry id="gloss-daemon">
<glossterm>daemon</glossterm>
<glossdef>
<para>A daemon is a computer program which runs in the background. In
general, most daemons are started at boot time via System V init
scripts, or through RC scripts on BSD-based systems.
<glossterm>mysqld</glossterm>,
the MySQL server, and
<glossterm>apache</glossterm>,
a web server, are generally run as daemons.</para>
</glossdef>
</glossentry>
<glossentry id="gloss-dos">
<glossterm>DOS Attack</glossterm>
<glossdef>
<para>A DOS, or Denial of Service attack, is when a user attempts to
deny access to a web server by repeatedly accessing a page or sending
malformed requests to a webserver. A D-DOS, or
Distributed Denial of Service attack, is when these requests come
from multiple sources at the same time. Unfortunately, these are much
more difficult to defend against.
</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-g">
<title>G</title>
<glossentry id="gloss-groups">
<glossterm>Groups</glossterm>
<glossdef>
<para>The word
<quote>Groups</quote>
has a very special meaning to Bugzilla. Bugzilla's main security
mechanism comes by placing users in groups, and assigning those
groups certain privileges to view bugs in particular
<glossterm>Products</glossterm>
in the
<glossterm>Bugzilla</glossterm>
database.</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-j">
<title>J</title>
<glossentry id="gloss-javascript">
<glossterm>JavaScript</glossterm>
<glossdef>
<para>JavaScript is cool, we should talk about it.
</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-m">
<title>M</title>
<glossentry id="gloss-mta">
<glossterm>Message Transport Agent</glossterm>
<acronym>MTA</acronym>
<glossdef>
<para>A Message Transport Agent is used to control the flow of email on a system.
The <ulink url="http://search.cpan.org/dist/Email-Send/lib/Email/Send.pm">Email::Send</ulink>
Perl module, which Bugzilla uses to send email, can be configured to
use many different underlying implementations for actually sending the
mail using the <option>mail_delivery_method</option> parameter.
Implementations other than <literal>sendmail</literal> require that the
<option>sendmailnow</option> param be set to <literal>on</literal>.
</para>
</glossdef>
</glossentry>
<glossentry id="gloss-mysql">
<glossterm>MySQL</glossterm>
<glossdef>
<para>MySQL is currently the required
<glossterm linkend="gloss-rdbms">RDBMS</glossterm> for Bugzilla. MySQL
can be downloaded from <ulink url="http://www.mysql.com"/>. While you
should familiarize yourself with all of the documentation, some high
points are:
</para>
<variablelist>
<varlistentry>
<term><ulink url="http://www.mysql.com/doc/en/Backup.html">Backup</ulink></term>
<listitem>
<para>Methods for backing up your Bugzilla database.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><ulink url="http://www.mysql.com/doc/en/Option_files.html">Option Files</ulink></term>
<listitem>
<para>Information about how to configure MySQL using
<filename>my.cnf</filename>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><ulink url="http://www.mysql.com/doc/en/Privilege_system.html">Privilege System</ulink></term>
<listitem>
<para>Much more detailed information about the suggestions in
<xref linkend="security-mysql"/>.
</para>
</listitem>
</varlistentry>
</variablelist>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-p">
<title>P</title>
<glossentry id="gloss-ppm">
<glossterm>Perl Package Manager</glossterm>
<acronym>PPM</acronym>
<glossdef>
<para><ulink url="http://aspn.activestate.com/ASPN/Downloads/ActivePerl/PPM/"/>
</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm id="gloss-product">Product</glossterm>
<glossdef>
<para>A Product is a broad category of types of bugs, normally
representing a single piece of software or entity. In general,
there are several Components to a Product. A Product may define a
group (used for security) for all bugs entered into
its Components.</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm>Perl</glossterm>
<glossdef>
<para>First written by Larry Wall, Perl is a remarkable program
language. It has the benefits of the flexibility of an interpreted
scripting language (such as shell script), combined with the speed
and power of a compiled language, such as C.
<glossterm>Bugzilla</glossterm>
is maintained in Perl.</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-q">
<title>Q</title>
<glossentry>
<glossterm>QA</glossterm>
<glossdef>
<para>
<quote>QA</quote>,
<quote>Q/A</quote>, and
<quote>Q.A.</quote>
are short for
<quote>Quality Assurance</quote>.
In most large software development organizations, there is a team
devoted to ensuring the product meets minimum standards before
shipping. This team will also generally want to track the progress of
bugs over their life cycle, thus the need for the
<quote>QA Contact</quote>
field in a bug.</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-r">
<title>R</title>
<glossentry id="gloss-rdbms">
<glossterm>Relational DataBase Management System</glossterm>
<acronym>RDBMS</acronym>
<glossdef>
<para>A relational database management system is a database system
that stores information in tables that are related to each other.
</para>
</glossdef>
</glossentry>
<glossentry id="gloss-regexp">
<glossterm>Regular Expression</glossterm>
<acronym>regexp</acronym>
<glossdef>
<para>A regular expression is an expression used for pattern matching.
<ulink url="http://perldoc.com/perl5.6/pod/perlre.html#Regular-Expressions">Documentation</ulink>
</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-s">
<title>S</title>
<glossentry id="gloss-service">
<glossterm>Service</glossterm>
<glossdef>
<para>In Windows NT environment, a boot-time background application
is referred to as a service. These are generally managed through the
control panel while logged in as an account with
<quote>Administrator</quote> level capabilities. For more
information, consult your Windows manual or the MSKB.
</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm>
<acronym>SGML</acronym>
</glossterm>
<glossdef>
<para>
<acronym>SGML</acronym>
stands for
<quote>Standard Generalized Markup Language</quote>.
Created in the 1980's to provide an extensible means to maintain
documentation based upon content instead of presentation,
<acronym>SGML</acronym>
has withstood the test of time as a robust, powerful language.
<glossterm>
<acronym>XML</acronym>
</glossterm>
is the
<quote>baby brother</quote>
of SGML; any valid
<acronym>XML</acronym>
document it, by definition, a valid
<acronym>SGML</acronym>
document. The document you are reading is written and maintained in
<acronym>SGML</acronym>,
and is also valid
<acronym>XML</acronym>
if you modify the Document Type Definition.</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-t">
<title>T</title>
<glossentry id="gloss-target-milestone" xreflabel="Target Milestone">
<glossterm>Target Milestone</glossterm>
<glossdef>
<para>Target Milestones are Product goals. They are configurable on a
per-Product basis. Most software development houses have a concept of
<quote>milestones</quote>
where the people funding a project expect certain functionality on
certain dates. Bugzilla facilitates meeting these milestones by
giving you the ability to declare by which milestone a bug will be
fixed, or an enhancement will be implemented.</para>
</glossdef>
</glossentry>
<glossentry id="gloss-tcl">
<glossterm>Tool Command Language</glossterm>
<acronym>TCL</acronym>
<glossdef>
<para>TCL is an open source scripting language available for Windows,
Macintosh, and Unix based systems. Bugzilla 1.0 was written in TCL but
never released. The first release of Bugzilla was 2.0, which was when
it was ported to perl.
</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv id="gloss-z">
<title>Z</title>
<glossentry id="gloss-zarro">
<glossterm>Zarro Boogs Found</glossterm>
<glossdef>
<para>This is just a goofy way of saying that there were no bugs
found matching your query. When asked to explain this message,
Terry had the following to say:
</para>
<blockquote>
<attribution>Terry Weissman</attribution>
<para>I've been asked to explain this ... way back when, when
Netscape released version 4.0 of its browser, we had a release
party. Naturally, there had been a big push to try and fix every
known bug before the release. Naturally, that hadn't actually
happened. (This is not unique to Netscape or to 4.0; the same thing
has happened with every software project I've ever seen.) Anyway,
at the release party, T-shirts were handed out that said something
like "Netscape 4.0: Zarro Boogs". Just like the software, the
T-shirt had no known bugs. Uh-huh.
</para>
<para>So, when you query for a list of bugs, and it gets no results,
you can think of this as a friendly reminder. Of *course* there are
bugs matching your query, they just aren't in the bugsystem yet...
</para>
</blockquote>
</glossdef>
</glossentry>
</glossdiv>
</glossary>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

View File

@@ -1,21 +0,0 @@
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

File diff suppressed because it is too large Load Diff

View File

@@ -1,124 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<!-- Keep these tools listings in alphabetical order please. -MPB -->
<section id="integration">
<title>Integrating Bugzilla with Third-Party Tools</title>
<section id="bonsai"
xreflabel="Bonsai, the Mozilla automated CVS management system">
<title>Bonsai</title>
<para>Bonsai is a web-based tool for managing
<xref linkend="cvs" />
. Using Bonsai, administrators can control open/closed status of trees,
query a fast relational database back-end for change, branch, and comment
information, and view changes made since the last time the tree was
closed. Bonsai
also integrates with
<xref linkend="tinderbox" />.
</para>
</section>
<section id="cvs" xreflabel="CVS, the Concurrent Versioning System">
<title>CVS</title>
<para>CVS integration is best accomplished, at this point, using the
Bugzilla Email Gateway.</para>
<para>Follow the instructions in this Guide for enabling Bugzilla e-mail
integration. Ensure that your check-in script sends an email to your
Bugzilla e-mail gateway with the subject of
<quote>[Bug XXXX]</quote>,
and you can have CVS check-in comments append to your Bugzilla bug. If
you want to have the bug be closed automatically, you'll have to modify
the <filename>contrib/bugzilla_email_append.pl</filename> script.
</para>
<para>There is also a CVSZilla project, based upon somewhat dated
Bugzilla code, to integrate CVS and Bugzilla through CVS' ability to
email. Check it out at: <ulink url="http://www.cvszilla.org/"/>.
</para>
<para>Another system capable of CVS integration with Bugzilla is
Scmbug. This system provides generic integration of Source code
Configuration Management with Bugtracking. Check it out at: <ulink
url="http://freshmeat.net/projects/scmbug/"/>.
</para>
</section>
<section id="scm"
xreflabel="Perforce SCM (Fast Software Configuration Management System, a powerful commercial alternative to CVS">
<title>Perforce SCM</title>
<para>You can find the project page for Bugzilla and Teamtrack Perforce
integration (p4dti) at:
<ulink url="http://www.ravenbrook.com/project/p4dti/"/>
.
<quote>p4dti</quote>
is now an officially supported product from Perforce, and you can find
the "Perforce Public Depot" p4dti page at
<ulink url="http://public.perforce.com/public/perforce/p4dti/index.html"/>
.</para>
<para>Integration of Perforce with Bugzilla, once patches are applied, is
seamless. Perforce replication information will appear below the comments
of each bug. Be certain you have a matching set of patches for the
Bugzilla version you are installing. p4dti is designed to support
multiple defect trackers, and maintains its own documentation for it.
Please consult the pages linked above for further information.</para>
</section>
<section id="svn"
xreflabel="Subversion, a compelling replacement for CVS">
<title>Subversion</title>
<para>Subversion is a free/open-source version control system,
designed to overcome various limitations of CVS. Integration of
Subversion with Bugzilla is possible using Scmbug, a system
providing generic integration of Source Code Configuration
Management with Bugtracking. Scmbug is available at <ulink
url="http://freshmeat.net/projects/scmbug/"/>.</para>
</section>
<section id="tinderbox"
xreflabel="Tinderbox, the Mozilla automated build management system">
<title>Tinderbox/Tinderbox2</title>
<para>Tinderbox is a continuous-build system which can integrate with
Bugzilla - see
<ulink url="http://www.mozilla.org/projects/tinderbox"/> for details
of Tinderbox, and
<ulink url="http://tinderbox.mozilla.org/showbuilds.cgi"/> to see it
in action.</para>
</section>
</section>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

View File

@@ -1,121 +0,0 @@
<chapter id="introduction">
<title>Introduction</title>
<section id="what-is-bugzilla">
<title>What is Bugzilla?</title>
<para>
Bugzilla is a bug- or issue-tracking system. Bug-tracking
systems allow individual or groups of developers effectively to keep track
of outstanding problems with their products.
</para>
<para><emphasis>Do we need more here?</emphasis></para>
</section>
<section id="why-tracking">
<title>Why use a bug-tracking system?</title>
<para>Those who do not use a bug-tracking system tend to rely on
shared lists, email, spreadsheets and/or Post-It notes to monitor the
status of defects. This procedure
is usually error-prone and tends to cause those bugs judged least
significant by developers to be dropped or ignored.</para>
<para>Integrated defect-tracking systems make sure that nothing gets
swept under the carpet; they provide a method of creating, storing,
arranging and processing defect reports and enhancement requests.</para>
</section>
<section id="why-bugzilla">
<title>Why use Bugzilla?</title>
<para>Bugzilla is the leading open-source/free software bug tracking
system. It boasts many advanced features, including:
<itemizedlist>
<listitem>
<para>Powerful searching</para>
</listitem>
<listitem>
<para>User-configurable email notifications of bug changes</para>
</listitem>
<listitem>
<para>Full change history</para>
</listitem>
<listitem>
<para>Inter-bug dependency tracking and graphing</para>
</listitem>
<listitem>
<para>Excellent attachment management</para>
</listitem>
<listitem>
<para>Integrated, product-based, granular security schema</para>
</listitem>
<listitem>
<para>Fully security-audited, and runs under Perl's taint mode</para>
</listitem>
<listitem>
<para>A robust, stable RDBMS back-end</para>
</listitem>
<listitem>
<para>Completely customizable and/or localizable web user
interface</para>
</listitem>
<listitem>
<para>Additional XML, email and console interfaces</para>
</listitem>
<listitem>
<para>Extensive configurability</para>
</listitem>
<listitem>
<para>Smooth upgrade pathway between versions</para>
</listitem>
</itemizedlist>
</para>
<para>Bugzilla is very adaptable to various situations. Known uses
currently include IT support queues, Systems Administration deployment
management, chip design and development problem tracking (both
pre-and-post fabrication), and software and hardware bug tracking for
luminaries such as Redhat, NASA, Linux-Mandrake, and VA Systems.
Combined with systems such as
<ulink url="http://www.cvshome.org">CVS</ulink>,
<ulink url="http://www.mozilla.org/bonsai.html">Bonsai</ulink>, or
<ulink url="http://www.perforce.com">Perforce SCM</ulink>, Bugzilla
provides a powerful, easy-to-use configuration management solution.</para>
</section>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

View File

@@ -1,197 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<appendix id="install-perlmodules-manual">
<title>Manual Installation of Perl Modules</title>
<section id="modules-manual-instructions">
<title>Instructions</title>
<para>
If you need to install Perl modules manually, here's how it's done.
Download the module using the link given in the next section, and then
apply this magic incantation, as root:
</para>
<para>
<screen><prompt>bash#</prompt> tar -xzvf &lt;module&gt;.tar.gz
<prompt>bash#</prompt> cd &lt;module&gt;
<prompt>bash#</prompt> perl Makefile.PL
<prompt>bash#</prompt> make
<prompt>bash#</prompt> make test
<prompt>bash#</prompt> make install</screen>
</para>
<note>
<para>
In order to compile source code under Windows you will need to obtain
a 'make' utility. The <command>nmake</command> utility provided with
Microsoft Visual C++ may be used. As an alternative, there is a
utility called <command>dmake</command> available from CPAN which is
written entirely in Perl.
</para>
<para>
As described in <xref linkend="modules-manual-download" />, however, most
packages already exist and are available from ActiveState or theory58S.
We highly recommend that you install them using the ppm GUI available with
ActiveState and to add the theory58S repository to your list of repositories.
</para>
</note>
</section>
<section id="modules-manual-download">
<title>Download Locations</title>
<note>
<para>
Running Bugzilla on Windows requires the use of ActiveState
Perl 5.8.1 or higher. Many modules already exist in the core
distribution of ActiveState Perl. Additional modules can be downloaded
from <ulink url="http://theoryx5.uwinnipeg.ca/ppms/" /> if you use
Perl 5.8.x or from <ulink url="http://cpan.uwinnipeg.ca/PPMPackages/10xx/" />
if you use Perl 5.10.x.
</para>
</note>
<para>
CGI:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/CGI.pm/"/>
Documentation: <ulink url="http://perldoc.perl.org/CGI.html"/>
</literallayout>
</para>
<para>
Data-Dumper:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/Data-Dumper/"/>
Documentation: <ulink url="http://search.cpan.org/dist/Data-Dumper/Dumper.pm"/>
</literallayout>
</para>
<para>
Date::Format (part of TimeDate):
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/TimeDate/"/>
Documentation: <ulink url="http://search.cpan.org/dist/TimeDate/lib/Date/Format.pm"/>
</literallayout>
</para>
<para>
DBI:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/DBI/"/>
Documentation: <ulink url="http://dbi.perl.org/docs/"/>
</literallayout>
</para>
<para>
DBD::mysql:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/DBD-mysql/"/>
Documentation: <ulink url="http://search.cpan.org/dist/DBD-mysql/lib/DBD/mysql.pm"/>
</literallayout>
</para>
<para>
DBD::Pg:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/DBD-Pg/"/>
Documentation: <ulink url="http://search.cpan.org/dist/DBD-Pg/Pg.pm"/>
</literallayout>
</para>
<para>
File::Spec:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/File-Spec/"/>
Documentation: <ulink url="http://perldoc.perl.org/File/Spec.html"/>
</literallayout>
</para>
<para>
Template-Toolkit:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/Template-Toolkit/"/>
Documentation: <ulink url="http://www.template-toolkit.org/docs.html"/>
</literallayout>
</para>
<para>
GD:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/GD/"/>
Documentation: <ulink url="http://search.cpan.org/dist/GD/GD.pm"/>
</literallayout>
</para>
<para>
Template::Plugin::GD:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/Template-GD/" />
Documentation: <ulink url="http://www.template-toolkit.org/docs/aqua/Modules/index.html" />
</literallayout>
</para>
<para>
MIME::Parser (part of MIME-tools):
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/MIME-tools/"/>
Documentation: <ulink url="http://search.cpan.org/dist/MIME-tools/lib/MIME/Parser.pm"/>
</literallayout>
</para>
</section>
<section id="modules-manual-optional">
<title>Optional Modules</title>
<para>
Chart::Base:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/Chart/"/>
Documentation: <ulink url="http://search.cpan.org/dist/Chart/Chart.pod"/>
</literallayout>
</para>
<para>
GD::Graph:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/GDGraph/"/>
Documentation: <ulink url="http://search.cpan.org/dist/GDGraph/Graph.pm"/>
</literallayout>
</para>
<para>
GD::Text::Align (part of GD::Text::Util):
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/GDTextUtil/"/>
Documentation: <ulink url="http://search.cpan.org/dist/GDTextUtil/Text/Align.pm"/>
</literallayout>
</para>
<para>
XML::Twig:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/XML-Twig/"/>
Documentation: <ulink url="http://standards.ieee.org/resources/spasystem/twig/twig_stable.html"/>
</literallayout>
</para>
<para>
PatchReader:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/author/JKEISER/PatchReader/"/>
Documentation: <ulink url="http://www.johnkeiser.com/mozilla/Patch_Viewer.html"/>
</literallayout>
</para>
<para>
Image::Magick:
<literallayout>
CPAN Download Page: <ulink url="http://search.cpan.org/dist/PerlMagick/"/>
Documentation: <ulink url="http://www.imagemagick.org/script/resources.php"/>
</literallayout>
</para>
</section>
</appendix>

View File

@@ -1,135 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<appendix id="patches" xreflabel="Useful Patches and Utilities for Bugzilla">
<title>Contrib</title>
<para>
There are a number of unofficial Bugzilla add-ons in the
<filename class="directory">$BUGZILLA_ROOT/contrib/</filename>
directory. This section documents them.
</para>
<section id="cmdline">
<title>Command-line Search Interface</title>
<para>
There are a suite of Unix utilities for searching Bugzilla from the
command line. They live in the
<filename class="directory">contrib/cmdline</filename> directory.
There are three files - <filename>query.conf</filename>,
<filename>buglist</filename> and <filename>bugs</filename>.
</para>
<warning>
<para>
These files pre-date the templatization work done as part of the
2.16 release, and have not been updated.
</para>
</warning>
<para>
<filename>query.conf</filename> contains the mapping from
options to field names and comparison types. Quoted option names
are <quote>grepped</quote> for, so it should be easy to edit this
file. Comments (#) have no effect; you must make sure these lines
do not contain any quoted <quote>option</quote>.
</para>
<para>
<filename>buglist</filename> is a shell script that submits a
Bugzilla query and writes the resulting HTML page to stdout.
It supports both short options, (such as <quote>-Afoo</quote>
or <quote>-Rbar</quote>) and long options (such
as <quote>--assignedto=foo</quote> or <quote>--reporter=bar</quote>).
If the first character of an option is not <quote>-</quote>, it is
treated as if it were prefixed with <quote>--default=</quote>.
</para>
<para>
The column list is taken from the COLUMNLIST environment variable.
This is equivalent to the <quote>Change Columns</quote> option
that is available when you list bugs in buglist.cgi. If you have
already used Bugzilla, grep for COLUMNLIST in your cookies file
to see your current COLUMNLIST setting.
</para>
<para>
<filename>bugs</filename> is a simple shell script which calls
<filename>buglist</filename> and extracts the
bug numbers from the output. Adding the prefix
<quote>http://bugzilla.mozilla.org/buglist.cgi?bug_id=</quote>
turns the bug list into a working link if any bugs are found.
Counting bugs is easy. Pipe the results through
<command>sed -e 's/,/ /g' | wc | awk '{printf $2 "\n"}'</command>
</para>
<para>
Akkana Peck says she has good results piping
<filename>buglist</filename> output through
<command>w3m -T text/html -dump</command>
</para>
</section>
<section id="cmdline-bugmail">
<title>Command-line 'Send Unsent Bug-mail' tool</title>
<para>
Within the <filename class="directory">contrib</filename> directory
exists a utility with the descriptive (if compact) name
of <filename>sendunsentbugmail.pl</filename>. The purpose of this
script is, simply, to send out any bug-related mail that should
have been sent by now, but for one reason or another has not.
</para>
<para>
To accomplish this task, <filename>sendunsentbugmail.pl</filename> uses
the same mechanism as the <filename>sanitycheck.cgi</filename> script;
it scans through the entire database looking for bugs with changes that
were made more than 30 minutes ago, but where there is no record of
anyone related to that bug having been sent mail. Having compiled a list,
it then uses the standard rules to determine who gets mail, and sends it
out.
</para>
<para>
As the script runs, it indicates the bug for which it is currently
sending mail; when it has finished, it gives a numerical count of how
many mails were sent and how many people were excluded. (Individual
user names are not recorded or displayed.) If the script produces
no output, that means no unsent mail was detected.
</para>
<para>
<emphasis>Usage</emphasis>: move the sendunsentbugmail.pl script
up into the main directory, ensure it has execute permission, and run it
from the command line (or from a cron job) with no parameters.
</para>
</section>
</appendix>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

View File

@@ -1,77 +0,0 @@
<!-- <!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> -->
<appendix id="downloadlinks">
<title>Software Download Links</title>
<para>All of these sites are current as of April, 2001. Hopefully they'll
stay current for a while.</para>
<para>Apache Web Server:
<ulink url="http://www.apache.org/"/>
Optional web server for Bugzilla, but recommended because of broad user
base and support.</para>
<para>Bugzilla:
<ulink url="http://www.bugzilla.org/"/>
</para>
<para>MySQL:
<ulink url="http://www.mysql.com/"/>
</para>
<para>Perl:
<ulink url="http://www.perl.org/"/>
</para>
<para>CPAN:
<ulink url="http://www.cpan.org/"/>
</para>
<para>DBI Perl module:
<ulink url="http://www.cpan.org/modules/by-module/DBI/"/>
</para>
<para>MySQL related Perl modules:
<ulink url="http://www.cpan.org/modules/by-module/Mysql/"/>
</para>
<para>TimeDate Perl module collection:
<ulink url="http://www.cpan.org/modules/by-module/Date/"/>
</para>
<para>GD Perl module:
<ulink url="http://www.cpan.org/modules/by-module/GD/"/>
Alternately, you should be able to find the latest version of GD at
<ulink url="http://www.boutell.com/gd/"/>
</para>
<para>Chart::Base module:
<ulink url="http://www.cpan.org/modules/by-module/Chart/"/>
</para>
<para>(But remember, Bundle::Bugzilla will install all the modules for you.)
</para>
</appendix>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End:
-->

View File

@@ -1,364 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<!-- $Id: security.xml,v 1.19.2.1 2008-07-13 16:44:28 mozilla%colinogilvie.co.uk Exp $ -->
<chapter id="security">
<title>Bugzilla Security</title>
<para>While some of the items in this chapter are related to the operating
system Bugzilla is running on or some of the support software required to
run Bugzilla, it is all related to protecting your data. This is not
intended to be a comprehensive guide to securing Linux, Apache, MySQL, or
any other piece of software mentioned. There is no substitute for active
administration and monitoring of a machine. The key to good security is
actually right in the middle of the word: <emphasis>U R It</emphasis>.
</para>
<para>While programmers in general always strive to write secure code,
accidents can and do happen. The best approach to security is to always
assume that the program you are working with isn't 100% secure and restrict
its access to other parts of your machine as much as possible.
</para>
<section id="security-os">
<title>Operating System</title>
<section id="security-os-ports">
<title>TCP/IP Ports</title>
<!-- TODO: Get exact number of ports -->
<para>The TCP/IP standard defines more than 65,000 ports for sending
and receiving traffic. Of those, Bugzilla needs exactly one to operate
(different configurations and options may require up to 3). You should
audit your server and make sure that you aren't listening on any ports
you don't need to be. It's also highly recommended that the server
Bugzilla resides on, along with any other machines you administer, be
placed behind some kind of firewall.
</para>
</section>
<section id="security-os-accounts">
<title>System User Accounts</title>
<para>Many <glossterm linkend="gloss-daemon">daemons</glossterm>, such
as Apache's <filename>httpd</filename> or MySQL's
<filename>mysqld</filename>, run as either <quote>root</quote> or
<quote>nobody</quote>. This is even worse on Windows machines where the
majority of <glossterm linkend="gloss-service">services</glossterm>
run as <quote>SYSTEM</quote>. While running as <quote>root</quote> or
<quote>SYSTEM</quote> introduces obvious security concerns, the
problems introduced by running everything as <quote>nobody</quote> may
not be so obvious. Basically, if you run every daemon as
<quote>nobody</quote> and one of them gets compromised it can
compromise every other daemon running as <quote>nobody</quote> on your
machine. For this reason, it is recommended that you create a user
account for each daemon.
</para>
<note>
<para>You will need to set the <option>webservergroup</option> option
in <filename>localconfig</filename> to the group your web server runs
as. This will allow <filename>./checksetup.pl</filename> to set file
permissions on Unix systems so that nothing is world-writable.
</para>
</note>
</section>
<section id="security-os-chroot">
<title>The <filename>chroot</filename> Jail</title>
<para>
If your system supports it, you may wish to consider running
Bugzilla inside of a <filename>chroot</filename> jail. This option
provides unprecedented security by restricting anything running
inside the jail from accessing any information outside of it. If you
wish to use this option, please consult the documentation that came
with your system.
</para>
</section>
</section>
<section id="security-mysql">
<title>MySQL</title>
<section id="security-mysql-account">
<title>The MySQL System Account</title>
<para>As mentioned in <xref linkend="security-os-accounts"/>, the MySQL
daemon should run as a non-privileged, unique user. Be sure to consult
the MySQL documentation or the documentation that came with your system
for instructions.
</para>
</section>
<section id="security-mysql-root">
<title>The MySQL <quote>root</quote> and <quote>anonymous</quote> Users</title>
<para>By default, MySQL comes with a <quote>root</quote> user with a
blank password and an <quote>anonymous</quote> user, also with a blank
password. In order to protect your data, the <quote>root</quote> user
should be given a password and the anonymous user should be disabled.
</para>
<example id="security-mysql-account-root">
<title>Assigning the MySQL <quote>root</quote> User a Password</title>
<screen>
<prompt>bash$</prompt> mysql mysql
<prompt>mysql&gt;</prompt> UPDATE user SET password = password('<replaceable>new_password</replaceable>') WHERE user = 'root';
<prompt>mysql&gt;</prompt> FLUSH PRIVILEGES;
</screen>
</example>
<example id="security-mysql-account-anonymous">
<title>Disabling the MySQL <quote>anonymous</quote> User</title>
<screen>
<prompt>bash$</prompt> mysql -u root -p mysql <co id="security-mysql-account-anonymous-mysql"/>
<prompt>Enter Password:</prompt> <replaceable>new_password</replaceable>
<prompt>mysql&gt;</prompt> DELETE FROM user WHERE user = '';
<prompt>mysql&gt;</prompt> FLUSH PRIVILEGES;
</screen>
<calloutlist>
<callout arearefs="security-mysql-account-anonymous-mysql">
<para>This command assumes that you have already completed
<xref linkend="security-mysql-account-root"/>.
</para>
</callout>
</calloutlist>
</example>
</section>
<section id="security-mysql-network">
<title>Network Access</title>
<para>If MySQL and your web server both run on the same machine and you
have no other reason to access MySQL remotely, then you should disable
the network access. This, along with the suggestion in
<xref linkend="security-os-ports"/>, will help protect your system from
any remote vulnerabilities in MySQL.
</para>
<example id="security-mysql-network-ex">
<title>Disabling Networking in MySQL</title>
<para>Simply enter the following in <filename>/etc/my.cnf</filename>:
<screen>
[mysqld]
# Prevent network access to MySQL.
skip-networking
</screen>
</para>
</example>
</section>
<!-- For possible addition in the future: How to better control the bugs user
<section id="security-mysql-bugs">
<title>The bugs User</title>
</section>
-->
</section>
<section id="security-webserver">
<title>Web server</title>
<section id="security-webserver-access">
<title>Disabling Remote Access to Bugzilla Configuration Files</title>
<para>
There are many files that are placed in the Bugzilla directory
area that should not be accessible from the web server. Because of the way
Bugzilla is currently layed out, the list of what should and should not
be accessible is rather complicated. A quick way is to run
<filename>testserver.pl</filename> to check if your web server serves
Bugzilla files as expected. If not, you may want to follow the few
steps below.
</para>
<tip>
<para>Bugzilla ships with the ability to create
<glossterm linkend="gloss-htaccess"><filename>.htaccess</filename></glossterm>
files that enforce these rules. Instructions for enabling these
directives in Apache can be found in <xref linkend="http-apache"/>
</para>
</tip>
<itemizedlist spacing="compact">
<listitem>
<para>In the main Bugzilla directory, you should:</para>
<itemizedlist spacing="compact">
<listitem>
<para>Block:
<simplelist type="inline">
<member><filename>*.pl</filename></member>
<member><filename>*localconfig*</filename></member>
</simplelist>
</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>In <filename class="directory">data</filename>:</para>
<itemizedlist spacing="compact">
<listitem>
<para>Block everything</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>In <filename class="directory">data/webdot</filename>:</para>
<itemizedlist spacing="compact">
<listitem>
<para>If you use a remote webdot server:</para>
<itemizedlist spacing="compact">
<listitem>
<para>Block everything</para>
</listitem>
<listitem>
<para>But allow
<simplelist type="inline">
<member><filename>*.dot</filename></member>
</simplelist>
only for the remote webdot server</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>Otherwise, if you use a local GraphViz:</para>
<itemizedlist spacing="compact">
<listitem>
<para>Block everything</para>
</listitem>
<listitem>
<para>But allow:
<simplelist type="inline">
<member><filename>*.png</filename></member>
<member><filename>*.gif</filename></member>
<member><filename>*.jpg</filename></member>
<member><filename>*.map</filename></member>
</simplelist>
</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>And if you don't use any dot:</para>
<itemizedlist spacing="compact">
<listitem>
<para>Block everything</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>In <filename class="directory">Bugzilla</filename>:</para>
<itemizedlist spacing="compact">
<listitem>
<para>Block everything</para>
</listitem>
</itemizedlist>
</listitem>
<listitem>
<para>In <filename class="directory">template</filename>:</para>
<itemizedlist spacing="compact">
<listitem>
<para>Block everything</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<para>Be sure to test that data that should not be accessed remotely is
properly blocked. Of particular interest is the localconfig file which
contains your database password. Also, be aware that many editors
create temporary and backup files in the working directory and that
those should also not be accessible. For more information, see
<ulink url="http://bugzilla.mozilla.org/show_bug.cgi?id=186383">bug 186383</ulink>
or
<ulink url="http://online.securityfocus.com/bid/6501">Bugtraq ID 6501</ulink>.
To test, simply run <filename>testserver.pl</filename>, as said above.
</para>
<tip>
<para>Be sure to check <xref linkend="http"/> for instructions
specific to the web server you use.
</para>
</tip>
</section>
</section>
<section id="security-bugzilla">
<title>Bugzilla</title>
<section id="security-bugzilla-charset">
<title>Prevent users injecting malicious Javascript</title>
<para>If you installed Bugzilla version 2.22 or later from scratch,
then the <emphasis>utf8</emphasis> parameter is switched on by default.
This makes Bugzilla explicitly set the character encoding, following
<ulink
url="http://www.cert.org/tech_tips/malicious_code_mitigation.html#3">a
CERT advisory</ulink> recommending exactly this.
The following therefore does not apply to you; just keep
<emphasis>utf8</emphasis> turned on.
</para>
<para>If you've upgraded from an older version, then it may be possible
for a Bugzilla user to take advantage of character set encoding
ambiguities to inject HTML into Bugzilla comments.
This could include malicious scripts.
This is because due to internationalization concerns, we are unable to
turn the <emphasis>utf8</emphasis> parameter on by default for upgraded
installations.
Turning it on manually will prevent this problem.
</para>
</section>
</section>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End: -->

View File

@@ -1,311 +0,0 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY % myents SYSTEM "bugzilla.ent">
%myents;
]>
<!-- $Id: troubleshooting.xml,v 1.13.4.1 2008-07-13 16:44:28 mozilla%colinogilvie.co.uk Exp $ -->
<appendix id="troubleshooting">
<title>Troubleshooting</title>
<para>This section gives solutions to common Bugzilla installation
problems. If none of the section headings seems to match your
problem, read the general advice.
</para>
<section id="general-advice">
<title>General Advice</title>
<para>If you can't get <filename>checksetup.pl</filename> to run to
completion, it normally explains what's wrong and how to fix it.
If you can't work it out, or if it's being uncommunicative, post
the errors in the
<ulink url="news://news.mozilla.org/mozilla.support.bugzilla">mozilla.support.bugzilla</ulink>
newsgroup.
</para>
<para>If you have made it all the way through
<xref linkend="installation"/> (Installation) and
<xref linkend="configuration"/> (Configuration) but accessing the Bugzilla
URL doesn't work, the first thing to do is to check your web server error
log. For Apache, this is often located at
<filename>/etc/logs/httpd/error_log</filename>. The error messages
you see may be self-explanatory enough to enable you to diagnose and
fix the problem. If not, see below for some commonly-encountered
errors. If that doesn't help, post the errors to the newsgroup.
</para>
<para>
Bugzilla can also log all user-based errors (and many code-based errors)
that occur, without polluting the web server's error log. To enable
Bugzilla error logging, create a file that Bugzilla can write to, named
<filename>errorlog</filename>, in the Bugzilla <filename>data</filename>
directory. Errors will be logged as they occur, and will include the type
of the error, the IP address and username (if available) of the user who
triggered the error, and the values of all environment variables; if a
form was being submitted, the data in the form will also be included.
To disable error logging, delete or rename the
<filename>errorlog</filename> file.
</para>
</section>
<section id="trbl-testserver">
<title>The Apache web server is not serving Bugzilla pages</title>
<para>After you have run <command>checksetup.pl</command> twice,
run <command>testserver.pl http://yoursite.yourdomain/yoururl</command>
to confirm that your web server is configured properly for
Bugzilla.
</para>
<programlisting>
<prompt>bash$</prompt> ./testserver.pl http://landfill.bugzilla.org/bugzilla-tip
TEST-OK Webserver is running under group id in $webservergroup.
TEST-OK Got ant picture.
TEST-OK Webserver is executing CGIs.
TEST-OK Webserver is preventing fetch of http://landfill.bugzilla.org/bugzilla-tip/localconfig.
</programlisting>
</section>
<section id="trbl-perlmodule">
<title>I installed a Perl module, but
<filename>checksetup.pl</filename> claims it's not installed!</title>
<para>This could be caused by one of two things:</para>
<orderedlist>
<listitem>
<para>You have two versions of Perl on your machine. You are installing
modules into one, and Bugzilla is using the other. Rerun the CPAN
commands (or manual compile) using the full path to Perl from the
top of <filename>checksetup.pl</filename>. This will make sure you
are installing the modules in the right place.
</para>
</listitem>
<listitem>
<para>The permissions on your library directories are set incorrectly.
They must, at the very least, be readable by the web server user or
group. It is recommended that they be world readable.
</para>
</listitem>
</orderedlist>
</section>
<section id="trbl-dbdSponge">
<title>DBD::Sponge::db prepare failed</title>
<para>The following error message may appear due to a bug in DBD::mysql
(over which the Bugzilla team have no control):
</para>
<programlisting><![CDATA[ DBD::Sponge::db prepare failed: Cannot determine NUM_OF_FIELDS at D:/Perl/site/lib/DBD/mysql.pm line 248.
SV = NULL(0x0) at 0x20fc444
REFCNT = 1
FLAGS = (PADBUSY,PADMY)
]]></programlisting>
<para>To fix this, go to
<filename>&lt;path-to-perl&gt;/lib/DBD/sponge.pm</filename>
in your Perl installation and replace
</para>
<programlisting><![CDATA[ my $numFields;
if ($attribs->{'NUM_OF_FIELDS'}) {
$numFields = $attribs->{'NUM_OF_FIELDS'};
} elsif ($attribs->{'NAME'}) {
$numFields = @{$attribs->{NAME}};
]]></programlisting>
<para>with</para>
<programlisting><![CDATA[ my $numFields;
if ($attribs->{'NUM_OF_FIELDS'}) {
$numFields = $attribs->{'NUM_OF_FIELDS'};
} elsif ($attribs->{'NAMES'}) {
$numFields = @{$attribs->{NAMES}};
]]></programlisting>
<para>(note the S added to NAME.)</para>
</section>
<section id="paranoid-security">
<title>cannot chdir(/var/spool/mqueue)</title>
<para>If you are installing Bugzilla on SuSE Linux, or some other
distributions with <quote>paranoid</quote> security options, it is
possible that the checksetup.pl script may fail with the error:
<programlisting><![CDATA[cannot chdir(/var/spool/mqueue): Permission denied
]]></programlisting>
</para>
<para>This is because your <filename>/var/spool/mqueue</filename>
directory has a mode of <computeroutput>drwx------</computeroutput>.
Type <command>chmod 755 <filename>/var/spool/mqueue</filename></command>
as root to fix this problem. This will allow any process running on your
machine the ability to <emphasis>read</emphasis> the
<filename>/var/spool/mqueue</filename> directory.
</para>
</section>
<section id="trbl-relogin-everyone">
<title>Everybody is constantly being forced to relogin</title>
<para>The most-likely cause is that the <quote>cookiepath</quote> parameter
is not set correctly in the Bugzilla configuration. You can change this (if
you're a Bugzilla administrator) from the editparams.cgi page via the web interface.
</para>
<para>The value of the cookiepath parameter should be the actual directory
containing your Bugzilla installation, <emphasis>as seen by the end-user's
web browser</emphasis>. Leading and trailing slashes are mandatory. You can
also set the cookiepath to any directory which is a parent of the Bugzilla
directory (such as '/', the root directory). But you can't put something
that isn't at least a partial match or it won't work. What you're actually
doing is restricting the end-user's browser to sending the cookies back only
to that directory.
</para>
<para>How do you know if you want your specific Bugzilla directory or the
whole site?
</para>
<para>If you have only one Bugzilla running on the server, and you don't
mind having other applications on the same server with it being able to see
the cookies (you might be doing this on purpose if you have other things on
your site that share authentication with Bugzilla), then you'll want to have
the cookiepath set to "/", or to a sufficiently-high enough directory that
all of the involved apps can see the cookies.
</para>
<example id="trbl-relogin-everyone-share">
<title>Examples of urlbase/cookiepath pairs for sharing login cookies</title>
<blockquote>
<literallayout>
urlbase is <ulink url="http://bugzilla.mozilla.org/"/>
cookiepath is /
urlbase is <ulink url="http://tools.mysite.tld/bugzilla/"/>
but you have http://tools.mysite.tld/someotherapp/ which shares
authentication with your Bugzilla
cookiepath is /
</literallayout>
</blockquote>
</example>
<para>On the other hand, if you have more than one Bugzilla running on the
server (some people do - we do on landfill) then you need to have the
cookiepath restricted enough so that the different Bugzillas don't
confuse their cookies with one another.
</para>
<example id="trbl-relogin-everyone-restrict">
<title>Examples of urlbase/cookiepath pairs to restrict the login cookie</title>
<blockquote>
<literallayout>
urlbase is <ulink url="http://landfill.bugzilla.org/bugzilla-tip/"/>
cookiepath is /bugzilla-tip/
urlbase is <ulink url="http://landfill.bugzilla.org/bugzilla-2.16-branch/"/>
cookiepath is /bugzilla-2.16-branch/
</literallayout>
</blockquote>
</example>
<para>If you had cookiepath set to <quote>/</quote> at any point in the
past and need to set it to something more restrictive
(i.e. <quote>/bugzilla/</quote>), you can safely do this without
requiring users to delete their Bugzilla-related cookies in their
browser (this is true starting with Bugzilla 2.18 and Bugzilla 2.16.5).
</para>
</section>
<section id="trbl-relogin-some">
<title>Some users are constantly being forced to relogin</title>
<para>First, make sure cookies are enabled in the user's browser.
</para>
<para>If that doesn't fix the problem, it may be that the user's ISP
implements a rotating proxy server. This causes the user's effective IP
address (the address which the Bugzilla server perceives him coming from)
to change periodically. Since Bugzilla cookies are tied to a specific IP
address, each time the effective address changes, the user will have to
log in again.
</para>
<para>If you are using 2.18 (or later), there is a
parameter called <quote>loginnetmask</quote>, which you can use to set
the number of bits of the user's IP address to require to be matched when
authenticating the cookies. If you set this to something less than 32,
then the user will be given a checkbox for <quote>Restrict this login to
my IP address</quote> on the login screen, which defaults to checked. If
they leave the box checked, Bugzilla will behave the same as it did
before, requiring an exact match on their IP address to remain logged in.
If they uncheck the box, then only the left side of their IP address (up
to the number of bits you specified in the parameter) has to match to
remain logged in.
</para>
</section>
<section id="trbl-index">
<title><filename>index.cgi</filename> doesn't show up unless specified in the URL</title>
<para>
You probably need to set up your web server in such a way that it
will serve the index.cgi page as an index page.
</para>
<para>
If you are using Apache, you can do this by adding
<filename>index.cgi</filename> to the end of the
<computeroutput>DirectoryIndex</computeroutput> line
as mentioned in <xref linkend="http-apache"/>.
</para>
</section>
<section id="trbl-passwd-encryption">
<title>
checksetup.pl reports "Client does not support authentication protocol
requested by server..."
</title>
<para>
This error is occurring because you are using the new password
encryption that comes with MySQL 4.1, while your
<filename>DBD::mysql</filename> module was compiled against an
older version of MySQL. If you recompile <filename>DBD::mysql</filename>
against the current MySQL libraries (or just obtain a newer version
of this module) then the error may go away.
</para>
<para>
If that does not fix the problem, or if you cannot recompile the
existing module (e.g. you're running Windows) and/or don't want to
replace it (e.g. you want to keep using a packaged version), then a
workaround is available from the MySQL docs:
<ulink url="http://dev.mysql.com/doc/mysql/en/Old_client.html"/>
</para>
</section>
</appendix>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-always-quote-attributes:t
sgml-auto-insert-required-elements:t
sgml-balanced-tag-edit:t
sgml-exposed-tags:nil
sgml-general-insert-case:lower
sgml-indent-data:t
sgml-indent-step:2
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
sgml-minimize-attributes:nil
sgml-namecase-general:t
sgml-omittag:t
sgml-parent-document:("Bugzilla-Guide.xml" "book" "chapter")
sgml-shorttag:t
sgml-tag-region-if-active:t
End: -->

File diff suppressed because it is too large Load Diff

View File

@@ -1,217 +0,0 @@
#!/usr/bin/perl -w
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Matthew Tuck <matty@chariot.net.au>
# Jacob Steenhagen <jake@bugzilla.org>
# Colin Ogilvie <colin.ogilvie@gmail.com>
# Max Kanat-Alexander <mkanat@bugzilla.org>
# This script compiles all the documentation.
use strict;
use Cwd;
# We need to be in this directory to use our libraries.
BEGIN {
require File::Basename;
import File::Basename qw(dirname);
chdir dirname($0);
}
use lib qw(.. ../lib lib);
# We only compile our POD if Pod::Simple is installed. We do the checks
# this way so that if there's a compile error in Pod::Simple::HTML::Bugzilla,
# makedocs doesn't just silently fail, but instead actually tells us there's
# a compile error.
my $pod_simple;
if (eval { require Pod::Simple }) {
require Pod::Simple::HTMLBatch::Bugzilla;
require Pod::Simple::HTML::Bugzilla;
$pod_simple = 1;
};
use Bugzilla::Install::Requirements
qw(REQUIRED_MODULES OPTIONAL_MODULES);
use Bugzilla::Constants qw(DB_MODULE BUGZILLA_VERSION);
###############################################################################
# Generate minimum version list
###############################################################################
my $modules = REQUIRED_MODULES;
my $opt_modules = OPTIONAL_MODULES;
open(ENTITIES, '>', 'bugzilla.ent') or die('Could not open bugzilla.ent: ' . $!);
print ENTITIES <<END_ENTITIES;
<?xml version="1.0" encoding="UTF-8" ?>
<!ENTITY bz-ver "3.3">
<!ENTITY bz-nextver "4.0">
<!ENTITY bz-date "2008-05-20">
<!ENTITY current-year "2008">
<!ENTITY landfillbase "http://landfill.bugzilla.org/bugzilla-tip/">
<!ENTITY bz "http://www.bugzilla.org/">
<!ENTITY bzg-bugs "<ulink url='https://bugzilla.mozilla.org/enter_bug.cgi?product=Bugzilla&amp;component=Documentation'>Bugzilla Documentation</ulink>">
<!ENTITY mysql "http://www.mysql.com/">
<!ENTITY min-perl-ver "5.8.1">
<!-- Module Versions -->
END_ENTITIES
foreach my $module (@$modules, @$opt_modules)
{
my $name = $module->{'module'};
$name =~ s/::/-/g;
$name = lc($name);
#This needs to be a string comparison, due to the modules having
#version numbers like 0.9.4
my $version = $module->{'version'} eq 0 ? 'any' : $module->{'version'};
print ENTITIES '<!ENTITY min-' . $name . '-ver "'.$version.'">' . "\n";
}
# CGI is a special case, because for Perl versions below 5.10, it has an
# optional version *and* a required version.
# We check @opt_modules first, then @modules, and pick the first we get.
# We'll get the optional one then, if it is given, otherwise the required one.
my ($cgi_opt) = grep($_->{module} eq 'CGI', @$opt_modules, @$modules);
print ENTITIES '<!ENTITY min-mp-cgi-ver "' . $cgi_opt->{version} . '">' . "\n";
print ENTITIES "\n <!-- Database Versions --> \n";
my $db_modules = DB_MODULE;
foreach my $db (keys %$db_modules) {
my $dbd = $db_modules->{$db}->{dbd};
my $name = $dbd->{module};
$name =~ s/::/-/g;
$name = lc($name);
my $version = $dbd->{version} || 'any';
my $db_version = $db_modules->{$db}->{'db_version'};
print ENTITIES '<!ENTITY min-' . $name . '-ver "'.$version.'">' . "\n";
print ENTITIES '<!ENTITY min-' . lc($db) . '-ver "'.$db_version.'">' . "\n";
}
close(ENTITIES);
###############################################################################
# Subs
###############################################################################
sub MakeDocs {
my ($name, $cmdline) = @_;
print "Creating $name documentation ...\n" if defined $name;
print "$cmdline\n\n";
system $cmdline;
print "\n";
}
sub make_pod {
print "Creating API documentation...\n";
my $converter = Pod::Simple::HTMLBatch::Bugzilla->new;
# Don't output progress information.
$converter->verbose(0);
$converter->html_render_class('Pod::Simple::HTML::Bugzilla');
my $doctype = Pod::Simple::HTML::Bugzilla->DOCTYPE;
my $content_type = Pod::Simple::HTML::Bugzilla->META_CT;
my $bz_version = BUGZILLA_VERSION;
my $contents_start = <<END_HTML;
$doctype
<html>
<head>
$content_type
<title>Bugzilla $bz_version API Documentation</title>
</head>
<body class="contentspage">
<h1>Bugzilla $bz_version API Documentation</h1>
END_HTML
$converter->contents_page_start($contents_start);
$converter->contents_page_end("</body></html>");
$converter->add_css('./../../../style.css');
$converter->javascript_flurry(0);
$converter->css_flurry(0);
$converter->batch_convert(['../../'], 'html/api/');
print "\n";
}
###############################################################################
# Make the docs ...
###############################################################################
my @langs;
# search for sub directories which have a 'xml' sub-directory
opendir(LANGS, './');
foreach my $dir (readdir(LANGS)) {
next if (($dir eq '.') || ($dir eq '..') || (! -d $dir));
if (-d "$dir/xml") {
push(@langs, $dir);
}
}
closedir(LANGS);
my $docparent = getcwd();
foreach my $lang (@langs) {
chdir "$docparent/$lang";
MakeDocs(undef, 'cp ../bugzilla.ent ./xml/');
if (!-d 'txt') {
unlink 'txt';
mkdir 'txt', 0755;
}
if (!-d 'pdf') {
unlink 'pdf';
mkdir 'pdf', 0755;
}
if (!-d 'html') {
unlink 'html';
mkdir 'html', 0755;
}
if (!-d 'html/api') {
unlink 'html/api';
mkdir 'html/api', 0755;
}
MakeDocs(undef, 'cp ../style.css html/api/');
make_pod() if $pod_simple;
MakeDocs('separate HTML', 'xmlto -m ../xsl/chunks.xsl -o html html ' .
'xml/Bugzilla-Guide.xml');
MakeDocs('big HTML', 'xmlto -m ../xsl/nochunks.xsl -o html html-nochunks ' .
'xml/Bugzilla-Guide.xml');
MakeDocs('big text', "lynx -dump -justify=off -nolist html/Bugzilla-Guide.html " .
"> txt/Bugzilla-Guide.txt");
if (! grep($_ eq "--with-pdf", @ARGV)) {
next;
}
MakeDocs('PDF', 'xmlto -m ../xsl/pdf.xsl -o pdf pdf xml/Bugzilla-Guide.xml');
}

View File

@@ -1,112 +0,0 @@
/* 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 Bugzilla Bug Tracking System.
*
* The Initial Developer of the Original Code is Everything Solved.
* Portions created by Everything Solved are Copyright (C) 2006
* Everything Solved. All Rights Reserved.
*
* Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
*/
body {
background: white;
color: #111;
padding: 0 1em;
margin: 0;
font-family: Verdana, Arial, sans-serif;
font-size: small;
}
td, th {
font-family: Verdana, Arial, sans-serif;
font-size: small;
}
a:link, a:active { color: #36415c; }
a:visited { color: #666; }
a:hover { color: #888; }
h1 {
font-size: 150%;
font-weight: bold;
border-bottom: 2px solid #ccc;
}
h2 {
font-size: 125%;
font-weight: bold;
border-bottom: 1px solid #ccc;
margin-bottom: 8px;
}
h3 {
font-size: 115%;
font-weight: bold;
margin-bottom: 0;
padding-bottom: 0;
}
/* This makes Description/Params/Returns look nice. */
dd { margin-top: .2em; }
dd p { margin-top: 0; }
dl { margin-bottom: 1em; }
/* This makes the names of functions slightly larger, in Gecko. */
body > dl > dt code { font-size: 1.35em; }
#pod h1 a, #pod h2 a, #pod h3 a {
color: #36415c;
text-decoration: none;
}
pre, code, tt, kbd, samp {
/* Unfortunately, the default monospace fonts on most browsers
look odd with relative sizing. */
font-size: 12px;
}
.code {
background: #eed;
border: 1px solid #ccc;
}
pre.code {
margin-left: 10px;
width: 90%;
padding: 10px;
}
/* Special styles for the Contents page */
.contentspage dt {
font-size: large;
font-weight: bold;
}
.pod_desc_table {
border-collapse: collapse;
table-layout: auto;
border: 1px solid #ccc;
}
.pod_desc_table th {
text-align: left;
}
.pod_desc_table td, .pod_desc_table th {
padding: .25em;
border-top: 1px solid #ccc;
}
.pod_desc_table .odd th, .pod_desc_table .odd td {
background-color: #eee;
}
.pod_desc_table

View File

@@ -1,102 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Nicer Filenames -->
<xsl:param name="use.id.as.filename" select="1"/>
<!-- Label sections if they aren't automatically labeled -->
<xsl:param name="section.autolabel" select="1"/>
<!-- Table of Contents Depth -->
<xsl:param name="toc.section.depth">1</xsl:param>
<!-- Set chunk parameters -->
<xsl:param name="chunk.section.depth" select="1"/>
<xsl:param name="chunk.first.sections" select="1"/>
<xsl:param name="chunker.output.encoding" select="UTF-8"/>
<!-- Show titles of next/previous page -->
<xsl:param name="navig.showtitles">1</xsl:param>
<!-- Tidy up the HTML a bit... -->
<xsl:param name="html.cleanup" select="1"/>
<xsl:param name="make.valid.html" select="1"/>
<xsl:param name="html.stylesheet">api/style.css</xsl:param>
<!-- make links nicer... -->
<xsl:param name="refentry.generate.title" select="1"/>
<xsl:param name="refentry.generate.name" select="0"/>
<!-- Use Graphics, specify their Path and Extension -->
<xsl:param name="admon.graphics" select="1"/>
<xsl:param name="admon.graphics.path">../images/</xsl:param>
<xsl:param name="admon.graphics.extension">.gif</xsl:param>
<xsl:param name="qanda.inherit.numeration" select="0" />
<!--
****
CODE BELOW HERE IS EXTRACTED AND EDITED FROM THE DOCBOOK XSL SOURCES
****
-->
<xsl:template match="simplelist[@type='inline']/member">
<xsl:apply-templates/>
</xsl:template>
<!--
To generate valid HTML, we need to redefine this section... Code extracted from
http://cvs.sourceforge.net/viewcvs.py/docbook/xsl/html/qandaset.xsl?rev=1.19&view=log
and modified below. Basic change: Remove the colspan attribute of the tr tags - no
other changes have been made to the document.
-->
<xsl:template match="qandadiv">
<xsl:variable name="preamble" select="*[name(.) != 'title'
and name(.) != 'titleabbrev'
and name(.) != 'qandadiv'
and name(.) != 'qandaentry']"/>
<xsl:if test="blockinfo/title|title">
<tr class="qandadiv">
<td align="left" valign="top" colspan="2">
<xsl:call-template name="anchor">
<xsl:with-param name="conditional" select="0"/>
</xsl:call-template>
<xsl:apply-templates select="(blockinfo/title|title)[1]"/>
</td>
</tr>
</xsl:if>
<xsl:variable name="toc">
<xsl:call-template name="dbhtml-attribute">
<xsl:with-param name="pis"
select="processing-instruction('dbhtml')"/>
<xsl:with-param name="attribute" select="'toc'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="toc.params">
<xsl:call-template name="find.path.params">
<xsl:with-param name="table" select="normalize-space($generate.toc)"/>
</xsl:call-template>
</xsl:variable>
<xsl:if test="(contains($toc.params, 'toc') and $toc != '0') or $toc = '1'">
<tr class="toc">
<td align="left" valign="top" colspan="2">
<xsl:call-template name="process.qanda.toc"/>
</td>
</tr>
</xsl:if>
<xsl:if test="$preamble">
<tr class="toc" >
<td align="left" valign="top" colspan="2">
<xsl:apply-templates select="$preamble"/>
</td>
</tr>
</xsl:if>
<xsl:apply-templates select="qandadiv|qandaentry"/>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Include default bugzilla XSL -->
<xsl:include href="bugzilla-docs.xsl"/>
<!-- Set Chunk Specific XSL Params -->
<xsl:param name="chunker.output.doctype-public">-//W3C//DTD HTML 4.01 Transitional//EN</xsl:param>
<xsl:param name="chunker.output.doctype-system">http://www.w3.org/TR/html4/loose.dtd</xsl:param>
<xsl:param name="chunk.section.depth" select="1"/>
<xsl:param name="chunk.first.sections" select="1"/>
<!-- Don't output filename list - mimic old behaviour-->
<xsl:param name="chunk.quietly" select="0" />
</xsl:stylesheet>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Include default bugzilla XSL -->
<xsl:include href="bugzilla-docs.xsl"/>
<!-- No other params necessary -->
</xsl:stylesheet>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">
<!-- Enable passivetex extensions -->
<xsl:param name="passivetex.extensions" select="1"/>
<xsl:param name="tablecolumns.extensions" select="1"/>
<!-- Show <ulink>s as footnotes -->
<xsl:param name="ulink.footnotes" select="1" />
<xsl:param name="ulink.show" select="1" />
<!-- Don't use Graphics -->
<xsl:param name="admon.graphics" select="0"/>
<xsl:param name="callout.graphics" select="'0'"/>
<xsl:template match="simplelist[@type='inline']/member">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,67 @@
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = xpwidgets support
#
# Dont build the DSO under the 'build' directory as windows does.
#
# The DSOs get built in the toolkit dir itself. Do this so that
# multiple implementations of widget can be built on the same
# source tree.
#
ifndef MOZ_MONOLITHIC_TOOLKIT
ifdef MOZ_ENABLE_GTK
DIRS += gtksuperwin
DIRS += gtk
endif
ifdef MOZ_ENABLE_MOTIF
DIRS += motif
endif
ifdef MOZ_ENABLE_XLIB
DIRS += xlib
endif
ifdef MOZ_ENABLE_QT
DIRS += qt
endif
else
DIRS += $(MOZ_WIDGET_TOOLKIT)
endif
# unix_services are only useful in unix, duh...
ifeq (,$(filter beos os2 rhapsody photon,$(MOZ_WIDGET_TOOLKIT)))
DIRS += unix_services
endif
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,100 @@
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = widget_gtk
REQUIRES = util img xpcom raptor netlib
CPPSRCS = \
nsAppShell.cpp \
nsButton.cpp \
nsCheckButton.cpp \
nsClipboard.cpp \
nsComboBox.cpp \
nsContextMenu.cpp \
nsDragService.cpp \
nsFilePicker.cpp \
nsFileWidget.cpp \
nsFontRetrieverService.cpp \
nsFontSizeIterator.cpp \
nsGtkEventHandler.cpp \
nsGtkUtils.cpp \
nsLabel.cpp \
nsListBox.cpp \
nsLookAndFeel.cpp \
nsMenu.cpp \
nsMenuBar.cpp \
nsMenuItem.cpp \
nsPopUpMenu.cpp \
nsRadioButton.cpp \
nsScrollbar.cpp \
nsSound.cpp \
nsTextAreaWidget.cpp \
nsTextHelper.cpp \
nsTextWidget.cpp \
nsToolkit.cpp \
nsWidget.cpp \
nsWidgetFactory.cpp \
nsWindow.cpp \
$(NULL)
SHARED_LIBRARY_LIBS = $(DIST)/lib/libraptorbasewidget_s.a
EXTRA_DSO_LDOPTS = \
$(MKSHLIB_FORCE_ALL) \
$(SHARED_LIBRARY_LIBS) \
$(MKSHLIB_UNFORCE_ALL) \
$(MOZ_COMPONENT_LIBS) \
-lraptorgfx \
$(NULL)
ifndef MOZ_MONOLITHIC_TOOLKIT
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lgtksuperwin $(MOZ_GTK_LDFLAGS)
else
EXTRA_DSO_LDOPTS += $(TK_LIBS)
endif
include $(topsrcdir)/config/rules.mk
ifndef MOZ_MONOLITHIC_TOOLKIT
CXXFLAGS += $(MOZ_GTK_CFLAGS)
CFLAGS += $(MOZ_GTK_CFLAGS)
else
CXXFLAGS += $(TK_CFLAGS)
CFLAGS += $(TK_CFLAGS)
endif
DEFINES += -D_IMPL_NS_WIDGET -DUSE_XIM
ifeq ($(OS_ARCH), Linux)
DEFINES += -D_BSD_SOURCE
endif
INCLUDES += \
-I$(srcdir)/../xpwidgets \
-I$(srcdir) \
$(NULL)
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile

View File

@@ -0,0 +1,292 @@
/* XPM */
static char * mozilla_icon_xpm[] = {
"32 32 257 2",
" c None",
". c #AA7303",
"+ c #A67003",
"@ c #B77C03",
"# c #8D6003",
"$ c #8D6004",
"% c #6C4A04",
"& c #3A2804",
"* c #6B4802",
"= c #9B6903",
"- c #5A2C04",
"; c #411B04",
"> c #9D6A03",
", c #7A5203",
"' c #510D04",
") c #6B1104",
"! c #7D5503",
"~ c #674604",
"{ c #C21E04",
"] c #C21D04",
"^ c #523804",
"/ c #513702",
"( c #552904",
"_ c #DD2204",
": c #DF2204",
"< c #582904",
"[ c #5F3F02",
"} c #6B2504",
"| c #FE2604",
"1 c #AB7303",
"2 c #9B6904",
"3 c #C31F04",
"4 c #FE2704",
"5 c #A81904",
"6 c #926304",
"7 c #4D3302",
"8 c #483104",
"9 c #C61E04",
"0 c #B11B04",
"a c #891604",
"b c #761204",
"c c #614304",
"d c #775102",
"e c #795102",
"f c #785102",
"g c #C58603",
"h c #642404",
"i c #B21A04",
"j c #1F0604",
"k c #550E04",
"l c #631004",
"m c #402404",
"n c #AF7703",
"o c #3D2902",
"p c #7F5602",
"q c #805604",
"r c #0C0904",
"s c #080604",
"t c #080706",
"u c #090604",
"v c #060404",
"w c #620F04",
"x c #7A1304",
"y c #030204",
"z c #570E04",
"A c #721204",
"B c #270704",
"C c #080504",
"D c #0A0604",
"E c #533804",
"F c #A56F02",
"G c #B87C03",
"H c #3B2804",
"I c #A51904",
"J c #FC2704",
"K c #D62004",
"L c #691004",
"M c #C01E04",
"N c #6D1004",
"O c #9C1804",
"P c #B31C04",
"Q c #150404",
"R c #801404",
"S c #DD2304",
"T c #120404",
"U c #130404",
"V c #500C04",
"W c #CC1E04",
"X c #AA1A04",
"Y c #100904",
"Z c #B47A03",
"` c #A77103",
" . c #513704",
".. c #891704",
"+. c #F62604",
"@. c #BA1D04",
"#. c #3C0A04",
"$. c #EB2304",
"%. c #DE2304",
"&. c #560E04",
"*. c #E82304",
"=. c #FE2804",
"-. c #BE1D04",
";. c #F12404",
">. c #661004",
",. c #020204",
"'. c #5E0F04",
"). c #A61A04",
"!. c #4A3204",
"~. c #BC7E03",
"{. c #8E6002",
"]. c #684604",
"^. c #390D04",
"/. c #EE2404",
"(. c #FE2904",
"_. c #7D1304",
":. c #8C1504",
"<. c #200604",
"[. c #A81A04",
"}. c #E72204",
"|. c #DA2004",
"1. c #070204",
"2. c #280704",
"3. c #543904",
"4. c #9F6C02",
"5. c #674602",
"6. c #B47B04",
"7. c #311004",
"8. c #B11C04",
"9. c #AA1B04",
"0. c #6A1104",
"a. c #801504",
"b. c #2B0704",
"c. c #09090A",
"d. c #450B04",
"e. c #360904",
"f. c #DC2204",
"g. c #EE2504",
"h. c #C11D04",
"i. c #6F1104",
"j. c #704B04",
"k. c #9C6902",
"l. c #A56F03",
"m. c #5F4004",
"n. c #8D1604",
"o. c #440A04",
"p. c #1A0504",
"q. c #931604",
"r. c #621004",
"s. c #7F1404",
"t. c #921704",
"u. c #F82504",
"v. c #F52504",
"w. c #981804",
"x. c #241804",
"y. c #5B3E04",
"z. c #D82204",
"A. c #D02004",
"B. c #DA2104",
"C. c #D52104",
"D. c #2A1A04",
"E. c #AC7403",
"F. c #2B1C04",
"G. c #D04004",
"H. c #FC3C04",
"I. c #F94E04",
"J. c #881504",
"K. c #FC2604",
"L. c #792804",
"M. c #AC7503",
"N. c #9A6803",
"O. c #782804",
"P. c #F66504",
"Q. c #F94B04",
"R. c #F46804",
"S. c #F46604",
"T. c #F76504",
"U. c #FB4204",
"V. c #C13D04",
"W. c #5D0E04",
"X. c #DA2204",
"Y. c #741604",
"Z. c #8C5E03",
"`. c #885B03",
" + c #8B1904",
".+ c #DE2204",
"++ c #D22D04",
"@+ c #C42D04",
"#+ c #580E04",
"$+ c #9F1804",
"%+ c #895D04",
"&+ c #D62204",
"*+ c #371904",
"=+ c #2C1A04",
"-+ c #4A0C04",
";+ c #140404",
">+ c #AB1A04",
",+ c #DA2304",
"'+ c #6A4702",
")+ c #754F02",
"!+ c #821404",
"~+ c #462B04",
"{+ c #B37A03",
"]+ c #B17803",
"^+ c #714C04",
"/+ c #580F04",
"(+ c #E32204",
"_+ c #DD2104",
":+ c #611D04",
"<+ c #BA7F03",
"[+ c #B27803",
"}+ c #6F1D04",
"|+ c #FD2704",
"1+ c #F22504",
"2+ c #634304",
"3+ c #875B03",
"4+ c #734F02",
"5+ c #805704",
"6+ c #1D0504",
"7+ c #DB2204",
"8+ c #EA2404",
"9+ c #2E0804",
"0+ c #815803",
"a+ c #941704",
"b+ c #C11E04",
"c+ c #391B04",
"d+ c #A77104",
"e+ c #B67C04",
"f+ c #371D04",
"g+ c #360A04",
"h+ c #573A04",
"i+ c #372604",
"j+ c #3E2104",
"k+ c #B57A03",
"l+ c #B57B03",
"m+ c #603F04",
"n+ c #430A04",
"o+ c #351904",
"p+ c #A36E03",
"q+ c #BE8103",
"r+ c #1D1404",
"s+ c #483004",
"t+ c #A26E03",
"u+ c #6D4B02",
"v+ c #825804",
"w+ c #0B0804",
"x+ c #976603",
"y+ c #815703",
"z+ c #926404",
"A+ c #895D03",
"B+ c #614202",
"C+ c #9A6804",
"D+ c #C88704",
"E+ c #C18303",
"F+ c #654302",
"G+ c #744F02",
"H+ c #704B02",
" ",
" . ",
" + @ ",
" # $ ",
" % & * ",
" = - ; > ",
" , ' ) ! ",
" ~ { ] ^ ",
" / ( _ : < [ ",
" . } | | } 1 ",
" 2 3 | 4 5 6 ",
" 7 8 9 0 a b c ",
" d e f f f d d d d d d g h i j k l m n d d d d d d d d d d d o ",
" p q r s s s s t s s u v w x y z A B C D D D D D s s s s E F ",
" G H I J 4 | 4 | K L L M N O P Q R | S T U V W X Y Z ",
" ` ...+.| 4 @.#.$.4 | %.&.*.4 =.-.;.>.,.'.).!.~. ",
" {.].^./.(.X _.;.| :.T <.[.| }.z | |.1.2.3.4. ",
" 5.6.7.8.9.0.a.b.c.d.e.f.g.h.&.| i.u j.k. ",
" l.m.n.o.p.q._.r.a.s.t.u.v.w.x.Z ",
" {.y.P z.R A.v.x j B.| C.D.E. ",
" F.G.H.I.4 | 4 t.J.f.K.L.M. ",
" N.O.P.Q.R.S.T.U.V.W.X.4 Y.Z. ",
" `. +4 =.| | .+++@+#+$+| K %+ ",
" %+&+| | | I *+=+-+;+>+,+&+x.'+ ",
" )+=+X.=.| !+~+{+]+^+,./+(+_+:+<+ ",
" [+}+|+1+) 2+3+ 4+5+6+7+8+9+0+ ",
" $ a+b+c+d+ e+f+0.g+h+ ",
" i+A j+k+ l+m+n+o+p+ ",
" q+r+s+t+ u+v+w+x+ ",
" y+z+A+ B+C+2 ",
" D+ E+F+ ",
" G+ H+ "};

View File

@@ -0,0 +1,63 @@
/* XPM */
static char * mozicon50_xpm[] = {
"50 51 9 1",
" c None",
". c #000000",
"+ c #FF0000",
"@ c #808000",
"# c #800000",
"$ c #FF6633",
"% c #990066",
"& c #FF00FF",
"* c #222222",
" ",
" @ ",
" $@ ",
" @@ ",
" @@$ ",
" $@*@ ",
" @@.@ ",
" @..@ ",
" $@..@@ ",
" $@##*@ ",
" @*#+.@ ",
" @.++.@$ ",
" $@.++.@$ ",
" @*#++#*@ ",
" @.++++.@ ",
" $@.++++.@$ ",
" @*#++++**@ ",
" @.#++++#.@ ",
" $@.++####.@ ",
" @@*+#*##*.@@ ",
"*@@@@@@@@@@@@@@@@@@@.#+..*##*#@@@@@@@@@@@@@@@@@@@*",
" *@@*................+#..*###.................@@* ",
" %@@@.#++++++++++++#**#*#++.###++*...#+++#.*@@* ",
" *@@.#+++++++++#.##++#+#+*.#+++#..##++#.@@@% ",
" $@..+++++++.#++++++##++++#++#...++*.@@$ ",
" @@*.#+++++.#+++++*.#++++##++#.*...@@ ",
" $@@.#+++#*++++#....#+++*#+++...*@$ ",
" *@@..++#*++#**.*.*+++#.#++*..@@$ ",
" $@*.++******#+++++#+#+++..@@ ",
" $@@.##..*$#**#+#*#++++..@@ ",
" $@@.#+#***##...#++++.*@@ ",
" %@@*++++++++#.#++++.@@ ",
" @.#+++++++++.##+++.@$ ",
" @.+$$$$$+$$$#*#+++*@@ ",
" $@*+$$$$$$$+$#.#+++#.@ ",
" @*#+++++++++++.#++++.@ ",
" @.#+++++++#*++.##+++.@$ ",
" $@.+++++++....#..+#++*@@ ",
" @@*+++++#.*@@@...*+++#.@ ",
" @.#++++#.@@@ @@..#++++.@ ",
" @.++++*.@@$ %@@..+++#.@@ ",
" $@.+++..@@* $@*.#+#**@ ",
" @@#+#.*@$% $@@.##..@ ",
" @.##.@@ @@..#.@$ ",
" $@.*.@@$ @@**.@$ ",
" $@.*@@ %$@@.*@ ",
" @.@@$ *@@.@ ",
" @@@$ %@@@$ ",
" $@@% %@@@ ",
" @@ $@ ",
" $ * "};

View File

@@ -0,0 +1,459 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "prmon.h"
#include "nsCOMPtr.h"
#include "nsAppShell.h"
#include "nsIAppShell.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
#include "nsICmdLineService.h"
#include "nsGtkEventHandler.h"
#include <stdlib.h>
#ifdef MOZ_GLE
#include <gle/gle.h>
#endif
#include "nsIWidget.h"
#include "nsIPref.h"
#include "glib.h"
struct OurGdkIOClosure {
GdkInputFunction function;
gpointer data;
};
static gboolean
our_gdk_io_invoke(GIOChannel* source, GIOCondition condition, gpointer data)
{
OurGdkIOClosure* ioc = (OurGdkIOClosure*) data;
if (ioc) {
(*ioc->function)(ioc->data, g_io_channel_unix_get_fd(source),
GDK_INPUT_READ);
}
return TRUE;
}
static void
our_gdk_io_destroy(gpointer data)
{
OurGdkIOClosure* ioc = (OurGdkIOClosure*) data;
if (ioc) {
g_free(ioc);
}
}
static gint
our_gdk_input_add (gint source,
GdkInputFunction function,
gpointer data,
gint priority)
{
guint result;
OurGdkIOClosure *closure = g_new (OurGdkIOClosure, 1);
GIOChannel *channel;
closure->function = function;
closure->data = data;
channel = g_io_channel_unix_new (source);
result = g_io_add_watch_full (channel, priority, G_IO_IN,
our_gdk_io_invoke,
closure, our_gdk_io_destroy);
g_io_channel_unref (channel);
return result;
}
//-------------------------------------------------------------------------
//
// XPCOM CIDs
//
//-------------------------------------------------------------------------
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kCmdLineServiceCID, NS_COMMANDLINE_SERVICE_CID);
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
// a linked, ordered list of event queues and their tokens
class EventQueueToken {
public:
EventQueueToken(nsIEventQueue *aQueue, const gint aToken);
virtual ~EventQueueToken();
nsIEventQueue *mQueue;
gint mToken;
EventQueueToken *mNext;
};
EventQueueToken::EventQueueToken(nsIEventQueue *aQueue, const gint aToken) {
mQueue = aQueue;
NS_IF_ADDREF(mQueue);
mToken = aToken;
mNext = 0;
}
EventQueueToken::~EventQueueToken(){
NS_IF_RELEASE(mQueue);
}
class EventQueueTokenQueue {
public:
EventQueueTokenQueue();
virtual ~EventQueueTokenQueue();
nsresult PushToken(nsIEventQueue *aQueue, gint aToken);
PRBool PopToken(nsIEventQueue *aQueue, gint *aToken);
private:
EventQueueToken *mHead;
};
EventQueueTokenQueue::EventQueueTokenQueue() {
mHead = 0;
}
EventQueueTokenQueue::~EventQueueTokenQueue() {
// if we reach this point with an empty token queue, well, fab. however,
// we expect the first event queue to still be active. so we take
// special care to unhook that queue (not that failing to do so seems
// to hurt anything). more queues than that would be an error.
//NS_ASSERTION(!mHead || !mHead->mNext, "event queue token list deleted when not empty");
// (and skip the assertion for now. we're leaking event queues because they
// are referenced by things that leak, so this assertion goes off a lot.)
if (mHead) {
gdk_input_remove(mHead->mToken);
delete mHead;
// and leak the rest. it's an error, anyway
}
}
nsresult EventQueueTokenQueue::PushToken(nsIEventQueue *aQueue, gint aToken) {
EventQueueToken *newToken = new EventQueueToken(aQueue, aToken);
NS_ASSERTION(newToken, "couldn't allocate token queue element");
if (!newToken)
return NS_ERROR_OUT_OF_MEMORY;
newToken->mNext = mHead;
mHead = newToken;
return NS_OK;
}
PRBool EventQueueTokenQueue::PopToken(nsIEventQueue *aQueue, gint *aToken) {
EventQueueToken *token, *lastToken;
PRBool found = PR_FALSE;
NS_ASSERTION(mHead, "attempt to retrieve event queue token from empty queue");
if (mHead)
NS_ASSERTION(mHead->mQueue == aQueue, "retrieving event queue from past head of queue queue");
token = mHead;
lastToken = 0;
while (token && token->mQueue != aQueue) {
lastToken = token;
token = token->mNext;
}
if (token) {
if (lastToken)
lastToken->mNext = token->mNext;
else
mHead = token->mNext;
found = PR_TRUE;
*aToken = token->mToken;
delete token;
}
return found;
}
//-------------------------------------------------------------------------
//
// nsAppShell constructor
//
//-------------------------------------------------------------------------
nsAppShell::nsAppShell()
{
NS_INIT_REFCNT();
mDispatchListener = 0;
mEventQueueTokens = new EventQueueTokenQueue();
// throw on error would really be civilized here
NS_ASSERTION(mEventQueueTokens, "couldn't allocate event queue token queue");
}
//-------------------------------------------------------------------------
//
// nsAppShell destructor
//
//-------------------------------------------------------------------------
nsAppShell::~nsAppShell()
{
delete mEventQueueTokens;
}
//-------------------------------------------------------------------------
//
// nsISupports implementation macro
//
//-------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(nsAppShell, nsIAppShell)
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::SetDispatchListener(nsDispatchListener* aDispatchListener)
{
mDispatchListener = aDispatchListener;
return NS_OK;
}
static void event_processor_callback(gpointer data,
gint source,
GdkInputCondition condition)
{
nsIEventQueue *eventQueue = (nsIEventQueue*)data;
if (eventQueue)
eventQueue->ProcessPendingEvents();
}
#define PREF_NCOLS "browser.ncols"
#define PREF_INSTALLCMAP "browser.installcmap"
static void
HandleColormapPrefs( void )
{
PRInt32 ivalue = 0;
PRBool bvalue;
nsresult rv;
/* The default is to do nothing. INSTALLCMAP has precedence over
NCOLS. Ignore the fact we can't do this if it fails, as it is
not critical */
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
if (NS_FAILED(rv) || (!prefs))
return;
/* first check ncols */
rv = prefs->GetIntPref(PREF_NCOLS, &ivalue);
if (NS_SUCCEEDED(rv) && ivalue >= 0 && ivalue <= 255 ) {
gdk_rgb_set_min_colors( ivalue );
return;
}
/* next check installcmap */
rv = prefs->GetBoolPref(PREF_INSTALLCMAP, &bvalue);
if (NS_SUCCEEDED(rv)) {
if ( PR_TRUE == bvalue )
gdk_rgb_set_min_colors( 255 ); // force it
else
gdk_rgb_set_min_colors( 0 );
}
}
//-------------------------------------------------------------------------
//
// Create the application shell
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Create(int *bac, char **bav)
{
gchar *home=nsnull;
gchar *path=nsnull;
int argc = bac ? *bac : 0;
char **argv = bav;
#if 1
nsresult rv;
NS_WITH_SERVICE(nsICmdLineService, cmdLineArgs, kCmdLineServiceCID, &rv);
if (NS_SUCCEEDED(rv))
{
rv = cmdLineArgs->GetArgc(&argc);
if(NS_FAILED(rv))
argc = bac ? *bac : 0;
rv = cmdLineArgs->GetArgv(&argv);
if(NS_FAILED(rv))
argv = bav;
}
#endif
gtk_set_locale ();
gtk_init (&argc, &argv);
// It is most convenient for us to intercept our events after
// they have been converted to GDK, but before GTK+ gets them
gdk_event_handler_set (handle_gdk_event, NULL, NULL);
#ifdef MOZ_GLE
gle_init (&argc, &argv);
#endif
// delete the cmdLineArgs thing?
HandleColormapPrefs();
gdk_rgb_init();
home = g_get_home_dir();
if ((char*)nsnull != home) {
path = g_strdup_printf("%s%c%s", home, G_DIR_SEPARATOR, ".gtkrc");
if ((char *)nsnull != path) {
gtk_rc_parse(path);
g_free(path);
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Spinup - do any preparation necessary for running a message loop
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Spinup()
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Spindown - do any cleanup necessary for finishing a message loop
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Spindown()
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Run
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Run()
{
NS_ADDREF_THIS();
nsresult rv = NS_OK;
nsIEventQueue * EQueue = nsnull;
// Get the event queue service
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) {
NS_ASSERTION("Could not obtain event queue service", PR_FALSE);
return rv;
}
#ifdef DEBUG
printf("Got the event queue from the service\n");
#endif /* DEBUG */
//Get the event queue for the thread.
rv = eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &EQueue);
// If a queue already present use it.
if (EQueue)
goto done;
// Create the event queue for the thread
rv = eventQService->CreateThreadEventQueue();
if (NS_OK != rv) {
NS_ASSERTION("Could not create the thread event queue", PR_FALSE);
return rv;
}
//Get the event queue for the thread
rv = eventQService->GetThreadEventQueue(PR_GetCurrentThread(), &EQueue);
if (NS_OK != rv) {
NS_ASSERTION("Could not obtain the thread event queue", PR_FALSE);
return rv;
}
done:
#ifdef DEBUG
printf("Calling gdk_input_add with event queue\n");
#endif /* DEBUG */
// (has to be called explicitly for this, the primordial appshell, because
// of startup ordering problems.)
ListenToEventQueue(EQueue, PR_TRUE);
gtk_main();
NS_IF_RELEASE(EQueue);
Release();
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Exit a message handler loop
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsAppShell::Exit()
{
gtk_main_quit ();
return NS_OK;
}
// does nothing. used by xp code with non-gtk expectations.
// this method will be removed once xp eventloops are working.
NS_IMETHODIMP nsAppShell::GetNativeEvent(PRBool &aRealEvent, void *& aEvent)
{
aRealEvent = PR_FALSE;
aEvent = 0;
return NS_OK;
}
// simply executes one iteration of the event loop. used by xp code with
// non-gtk expectations.
// this method will be removed once xp eventloops are working.
NS_IMETHODIMP nsAppShell::DispatchNativeEvent(PRBool aRealEvent, void *aEvent)
{
g_main_iteration(PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP nsAppShell::ListenToEventQueue(nsIEventQueue *aQueue,
PRBool aListen)
{
// tell gdk to listen to the event queue or not
gint queueToken;
if (aListen) {
queueToken = our_gdk_input_add(aQueue->GetEventQueueSelectFD(),
event_processor_callback,
aQueue, G_PRIORITY_DEFAULT_IDLE);
mEventQueueTokens->PushToken(aQueue, queueToken);
} else {
if (mEventQueueTokens->PopToken(aQueue, &queueToken))
gdk_input_remove(queueToken);
}
return NS_OK;
}

View File

@@ -0,0 +1,50 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsAppShell_h__
#define nsAppShell_h__
#include "nsIAppShell.h"
#include <gtk/gtk.h>
/**
* Native GTK+ Application shell wrapper
*/
class EventQueueTokenQueue;
class nsAppShell : public nsIAppShell
{
public:
nsAppShell();
virtual ~nsAppShell();
NS_DECL_ISUPPORTS
NS_DECL_NSIAPPSHELL
private:
nsDispatchListener *mDispatchListener;
EventQueueTokenQueue *mEventQueueTokens;
};
#endif // nsAppShell_h__

View File

@@ -0,0 +1,156 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsGtkEventHandler.h"
#include "nsButton.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsButton, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsButton, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsButton, nsIButton, nsIWidget)
//-------------------------------------------------------------------------
//
// nsButton constructor
//
//-------------------------------------------------------------------------
nsButton::nsButton() : nsWidget() , nsIButton()
{
}
//-------------------------------------------------------------------------
//
// Create the native Button widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsButton::CreateNative(GtkObject *parentWindow)
{
#ifdef USE_SUPERWIN
if (!GDK_IS_SUPERWIN(parentWindow)) {
g_print("Damn, brother. That's not a superwin.\n");
return NS_ERROR_FAILURE;
}
GdkSuperWin *superwin = GDK_SUPERWIN(parentWindow);
mMozBox = gtk_mozbox_new(superwin->bin_window);
#endif
mWidget = gtk_button_new_with_label("");
gtk_widget_set_name(mWidget, "nsButton");
#ifdef USE_SUPERWIN
// make sure that we put the scrollbar into the mozbox
gtk_container_add(GTK_CONTAINER(mMozBox), mWidget);
#endif /* USE_SUPERWIN */
return NS_OK;
}
//-------------------------------------------------------------------------
//
// nsButton destructor
//
//-------------------------------------------------------------------------
nsButton::~nsButton()
{
}
void nsButton::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mWidget);
InstallButtonReleaseSignal(mWidget);
InstallEnterNotifySignal(mWidget);
InstallLeaveNotifySignal(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsButton::SetLabel(const nsString& aText)
{
NS_ALLOC_STR_BUF(label, aText, 256);
gtk_label_set(GTK_LABEL(GTK_BIN (mWidget)->child), label);
NS_FREE_STR_BUF(label);
return (NS_OK);
}
//-------------------------------------------------------------------------
//
// Get this button label
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsButton::GetLabel(nsString& aBuffer)
{
char * text;
gtk_label_get(GTK_LABEL(GTK_BIN (mWidget)->child), &text);
aBuffer.SetLength(0);
aBuffer.Append(text);
return (NS_OK);
}
//-------------------------------------------------------------------------
//
// set font for button
//
//-------------------------------------------------------------------------
/* virtual */
void nsButton::SetFontNative(GdkFont *aFont)
{
GtkStyle *style = gtk_style_copy(GTK_BIN (mWidget)->child->style);
// gtk_style_copy ups the ref count of the font
gdk_font_unref (style->font);
style->font = aFont;
gdk_font_ref(style->font);
gtk_widget_set_style(GTK_BIN (mWidget)->child, style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsButton_h__
#define nsButton_h__
#include "nsWidget.h"
#include "nsIButton.h"
/**
* Native GTK+ button wrapper
*/
class nsButton : public nsWidget,
public nsIButton
{
public:
nsButton();
virtual ~nsButton();
NS_DECL_ISUPPORTS_INHERITED
// nsIButton part
NS_IMETHOD SetLabel(const nsString& aText);
NS_IMETHOD GetLabel(nsString& aBuffer);
virtual void SetFontNative(GdkFont *aFont);
protected:
NS_METHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
};
#endif // nsButton_h__

View File

@@ -0,0 +1,250 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsCheckButton.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsCheckButton, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsCheckButton, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsCheckButton, nsICheckButton, nsIWidget)
//-------------------------------------------------------------------------
//
// nsCheckButton constructor
//
//-------------------------------------------------------------------------
nsCheckButton::nsCheckButton() : nsWidget() , nsICheckButton()
{
NS_INIT_REFCNT();
mLabel = nsnull;
mCheckButton = nsnull;
mState = PR_FALSE;
}
//-------------------------------------------------------------------------
//
// nsCheckButton destructor
//
//-------------------------------------------------------------------------
nsCheckButton::~nsCheckButton()
{
}
void
nsCheckButton::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mCheckButton) {
mCheckButton = nsnull;
}
else if (aGtkWidget == mLabel) {
mLabel = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
//-------------------------------------------------------------------------
//
// Create the native CheckButton widget
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::CreateNative(GtkObject *parentWindow)
{
mWidget = gtk_event_box_new();
mCheckButton = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(mWidget), mCheckButton);
gtk_widget_show(mCheckButton);
gtk_widget_set_name(mWidget, "nsCheckButton");
return NS_OK;
}
void nsCheckButton::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mCheckButton);
InstallButtonReleaseSignal(mCheckButton);
InstallEnterNotifySignal(mWidget);
InstallLeaveNotifySignal(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
// Add in destroy callback
gtk_signal_connect(GTK_OBJECT(mCheckButton),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
InstallSignal((GtkWidget *)mCheckButton,
(gchar *)"toggled",
GTK_SIGNAL_FUNC(nsCheckButton::ToggledSignal));
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::SetState(const PRBool aState)
{
mState = aState;
if (mWidget && mCheckButton)
{
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mCheckButton);
item->active = (gboolean) mState;
gtk_widget_queue_draw(GTK_WIDGET(item));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::GetState(PRBool& aState)
{
aState = mState;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set this Checkbox label
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::SetLabel(const nsString& aText)
{
if (mWidget) {
NS_ALLOC_STR_BUF(label, aText, 256);
if (mLabel) {
gtk_label_set(GTK_LABEL(mLabel), label);
} else {
mLabel = gtk_label_new(label);
gtk_misc_set_alignment (GTK_MISC (mLabel), 0.0, 0.5);
gtk_container_add(GTK_CONTAINER(mCheckButton), mLabel);
gtk_widget_show(mLabel);
gtk_signal_connect(GTK_OBJECT(mLabel),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
}
NS_FREE_STR_BUF(label);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsCheckButton::GetLabel(nsString& aBuffer)
{
aBuffer.SetLength(0);
if (mWidget) {
char * text;
if (mLabel) {
gtk_label_get(GTK_LABEL(mLabel), &text);
aBuffer.Append(text);
}
}
return NS_OK;
}
/* virtual */ void
nsCheckButton::OnToggledSignal(const gboolean aState)
{
// Untoggle the sonofabitch
if (mWidget && mCheckButton)
{
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mCheckButton);
item->active = !item->active;
gtk_widget_queue_draw(GTK_WIDGET(item));
}
}
//////////////////////////////////////////////////////////////////////
/* static */ gint
nsCheckButton::ToggledSignal(GtkWidget * aWidget,
gpointer aData)
{
NS_ASSERTION( nsnull != aWidget, "widget is null");
nsCheckButton * button = (nsCheckButton *) aData;
NS_ASSERTION( nsnull != button, "instance pointer is null");
button->OnToggledSignal(GTK_TOGGLE_BUTTON(aWidget)->active);
return PR_TRUE;
}
//////////////////////////////////////////////////////////////////////
// SetBackgroundColor for CheckButton
/*virtual*/
void nsCheckButton::SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark)
{
// use same style copy as SetFont
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
style->bg[GTK_STATE_NORMAL]=*aColorNor;
// Mouse over button
style->bg[GTK_STATE_PRELIGHT]=*aColorBri;
// Button is down
style->bg[GTK_STATE_ACTIVE]=*aColorDark;
// other states too? (GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT,
// GTK_STATE_SELECTED, GTK_STATE_INSENSITIVE)
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
// set style for eventbox too
gtk_widget_set_style(mWidget, style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsCheckButton_h__
#define nsCheckButton_h__
#include "nsWidget.h"
#include "nsICheckButton.h"
/**
* Native GTK+ Checkbox wrapper
*/
class nsCheckButton : public nsWidget,
public nsICheckButton
{
public:
nsCheckButton();
virtual ~nsCheckButton();
NS_DECL_ISUPPORTS_INHERITED
// nsICheckButton part
NS_IMETHOD SetLabel(const nsString &aText);
NS_IMETHOD GetLabel(nsString &aBuffer);
NS_IMETHOD SetState(const PRBool aState);
NS_IMETHOD GetState(PRBool& aState);
virtual void OnToggledSignal(const gboolean aState);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
// Sets background for checkbutton
virtual void SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark);
GtkWidget *mLabel;
GtkWidget *mCheckButton;
// We need to maintain our own state to be in sync with the
// gecko check controlling frame.
PRBool mState;
private:
static gint ToggledSignal(GtkWidget * aWidget,
gpointer aData);
};
#endif // nsCheckButton_h__

View File

@@ -0,0 +1,872 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsClipboard.h"
#include "nsCOMPtr.h"
#include "nsISupportsArray.h"
#include "nsIClipboardOwner.h"
#include "nsITransferable.h" // kTextMime
#include "nsISupportsPrimitives.h"
#include "nsIWidget.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsWidgetsCID.h"
#include "nsXPIDLString.h"
#include "nsPrimitiveHelpers.h"
#include "nsVoidArray.h"
// The class statics:
GtkWidget* nsClipboard::sWidget = 0;
#if defined(DEBUG_mcafee) || defined(DEBUG_pavlov)
#define DEBUG_CLIPBOARD
#endif
enum {
TARGET_NONE,
TARGET_TEXT_PLAIN,
TARGET_TEXT_XIF,
TARGET_TEXT_UNICODE,
TARGET_TEXT_HTML,
TARGET_AOLMAIL,
TARGET_IMAGE_PNG,
TARGET_IMAGE_JPEG,
TARGET_IMAGE_GIF,
// compatibility types
TARGET_UTF8,
TARGET_UNKNOWN,
TARGET_LAST
};
static GdkAtom sSelTypes[TARGET_LAST];
//-------------------------------------------------------------------------
//
// nsClipboard constructor
//
//-------------------------------------------------------------------------
nsClipboard::nsClipboard() : nsBaseClipboard()
{
#ifdef DEBUG_CLIPBOARD
g_print("nsClipboard::nsClipboard()\n");
#endif /* DEBUG_CLIPBOARD */
//NS_INIT_REFCNT();
mIgnoreEmptyNotification = PR_FALSE;
mClipboardOwner = nsnull;
mTransferable = nsnull;
mSelectionData.data = nsnull;
mSelectionData.length = 0;
// initialize the widget, etc we're binding to
Init();
}
// XXX if GTK's internal code changes this isn't going to work
// copied from gtk code because it is a static function we can't get to it.
// need to bug owen taylor about getting this code public.
typedef struct _GtkSelectionTargetList GtkSelectionTargetList;
struct _GtkSelectionTargetList {
GdkAtom selection;
GtkTargetList *list;
};
static const char *gtk_selection_handler_key = "gtk-selection-handlers";
void __gtk_selection_target_list_remove (GtkWidget *widget)
{
GtkSelectionTargetList *sellist;
GList *tmp_list;
GList *lists;
lists = (GList*)gtk_object_get_data (GTK_OBJECT (widget), gtk_selection_handler_key);
tmp_list = lists;
while (tmp_list)
{
sellist = (GtkSelectionTargetList*)tmp_list->data;
gtk_target_list_unref (sellist->list);
g_free (sellist);
tmp_list = tmp_list->next;
}
g_list_free (lists);
gtk_object_set_data (GTK_OBJECT (widget), gtk_selection_handler_key, NULL);
}
//-------------------------------------------------------------------------
//
// nsClipboard destructor
//
//-------------------------------------------------------------------------
nsClipboard::~nsClipboard()
{
#ifdef DEBUG_CLIPBOARD
printf("nsClipboard::~nsClipboard()\n");
#endif /* DEBUG_CLIPBOARD */
// Remove all our event handlers:
if (sWidget &&
(gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == sWidget->window))
gtk_selection_remove_all(sWidget);
// free the selection data, if any
if (mSelectionData.data != nsnull)
g_free(mSelectionData.data);
nsClipboard *cb = (nsClipboard*)gtk_object_get_data(GTK_OBJECT(sWidget), "cb");
if (cb != nsnull)
{
NS_RELEASE(cb);
gtk_object_remove_data(GTK_OBJECT(sWidget), "cb");
}
if (sWidget)
{
gtk_widget_destroy(sWidget);
sWidget = nsnull;
}
}
//
// GTK Weirdness!
// This is here in the hope of being able to call
// gtk_selection_add_targets(w, GDK_SELECTION_PRIMARY,
// targets,
// 1);
// instead of
// gtk_selection_add_target(sWidget,
// GDK_SELECTION_PRIMARY,
// GDK_SELECTION_TYPE_STRING,
// GDK_SELECTION_TYPE_STRING);
// but it turns out that this changes the whole gtk selection model;
// when calling add_targets copy uses selection_clear_event and the
// data structure needs to be filled in in a way that we haven't
// figured out; when using add_target copy uses selection_get and
// the data structure is already filled in as much as it needs to be.
// Some gtk internals wizard will need to solve this mystery before
// we can use add_targets().
//static GtkTargetEntry targets[] = {
// { "strings n stuff", GDK_SELECTION_TYPE_STRING, GDK_SELECTION_TYPE_STRING }
//};
//
//-------------------------------------------------------------------------
void nsClipboard::Init(void)
{
#ifdef DEBUG_CLIPBOARD
g_print("nsClipboard::Init\n");
#endif
sSelTypes[TARGET_NONE] = GDK_NONE;
sSelTypes[TARGET_TEXT_PLAIN] = gdk_atom_intern(kTextMime, FALSE);
sSelTypes[TARGET_TEXT_XIF] = gdk_atom_intern(kXIFMime, FALSE);
sSelTypes[TARGET_TEXT_UNICODE] = gdk_atom_intern(kUnicodeMime, FALSE);
sSelTypes[TARGET_UTF8] = gdk_atom_intern("UTF8", FALSE);
sSelTypes[TARGET_TEXT_HTML] = gdk_atom_intern(kHTMLMime, FALSE);
sSelTypes[TARGET_AOLMAIL] = gdk_atom_intern(kAOLMailMime, FALSE);
sSelTypes[TARGET_IMAGE_PNG] = gdk_atom_intern(kPNGImageMime, FALSE);
sSelTypes[TARGET_IMAGE_JPEG] = gdk_atom_intern(kJPEGImageMime, FALSE);
sSelTypes[TARGET_IMAGE_GIF] = gdk_atom_intern(kGIFImageMime, FALSE);
// compatibility with other apps
// create invisible widget to use for the clipboard
sWidget = gtk_invisible_new();
// add the clipboard pointer to the widget so we can get it.
gtk_object_set_data(GTK_OBJECT(sWidget), "cb", this);
NS_ADDREF_THIS();
// Handle selection requests if we called gtk_selection_add_target:
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_get",
GTK_SIGNAL_FUNC(nsClipboard::SelectionGetCB),
nsnull);
// When someone else takes the selection away:
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_clear_event",
GTK_SIGNAL_FUNC(nsClipboard::SelectionClearCB),
nsnull);
// Set up the paste handler:
gtk_signal_connect(GTK_OBJECT(sWidget), "selection_received",
GTK_SIGNAL_FUNC(nsClipboard::SelectionReceivedCB),
nsnull);
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsClipboard::SetNativeClipboardData()
{
mIgnoreEmptyNotification = PR_TRUE;
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SetNativeClipboardData()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (nsnull == mTransferable) {
printf("nsClipboard::SetNativeClipboardData(): no transferable!\n");
return NS_ERROR_FAILURE;
}
// are we already the owner?
if (gdk_selection_owner_get(GDK_SELECTION_PRIMARY) == sWidget->window)
{
// if so, clear all the targets
__gtk_selection_target_list_remove(sWidget);
// gtk_selection_remove_all(sWidget);
}
// we arn't already the owner, so we will become it
gint have_selection = gtk_selection_owner_set(sWidget,
GDK_SELECTION_PRIMARY,
GDK_CURRENT_TIME);
if (have_selection == 0)
return NS_ERROR_FAILURE;
// get flavor list that includes all flavors that can be written (including ones
// obtained through conversion)
nsCOMPtr<nsISupportsArray> flavorList;
nsresult errCode = mTransferable->FlavorsTransferableCanExport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return NS_ERROR_FAILURE;
PRUint32 cnt;
flavorList->Count(&cnt);
for ( PRUint32 i=0; i<cnt; ++i )
{
nsCOMPtr<nsISupports> genericFlavor;
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
gint format = GetFormat(flavorStr);
// add these types as selection targets
RegisterFormat(format);
}
}
mIgnoreEmptyNotification = PR_FALSE;
return NS_OK;
}
void nsClipboard::AddTarget(GdkAtom aAtom)
{
gtk_selection_add_target(sWidget,
GDK_SELECTION_PRIMARY,
aAtom, aAtom);
}
gint nsClipboard::GetFormat(const char* aMimeStr)
{
gint type = TARGET_NONE;
nsCAutoString mimeStr ( CBufDescriptor(NS_CONST_CAST(char*,aMimeStr), PR_TRUE, PL_strlen(aMimeStr)+1) );
#ifdef DEBUG_CLIPBOARD
g_print(" nsClipboard::GetFormat(%s)\n", aMimeStr);
#endif
if (mimeStr.Equals(kTextMime)) {
type = TARGET_TEXT_PLAIN;
} else if (mimeStr.Equals("STRING")) {
type = TARGET_TEXT_PLAIN;
} else if (mimeStr.Equals(kXIFMime)) {
type = TARGET_TEXT_XIF;
} else if (mimeStr.Equals(kUnicodeMime)) {
type = TARGET_TEXT_UNICODE;
} else if (mimeStr.Equals(kHTMLMime)) {
type = TARGET_TEXT_HTML;
} else if (mimeStr.Equals(kAOLMailMime)) {
type = TARGET_AOLMAIL;
} else if (mimeStr.Equals(kPNGImageMime)) {
type = TARGET_IMAGE_PNG;
} else if (mimeStr.Equals(kJPEGImageMime)) {
type = TARGET_IMAGE_JPEG;
} else if (mimeStr.Equals(kGIFImageMime)) {
type = TARGET_IMAGE_GIF;
}
#ifdef WE_DO_DND
else if (mimeStr.Equals(kDropFilesMime)) {
format = CF_HDROP;
} else {
format = ::RegisterClipboardFormat(aMimeStr);
}
#endif
return type;
}
void nsClipboard::RegisterFormat(gint format)
{
#ifdef DEBUG_CLIPBOARD
g_print(" nsClipboard::RegisterFormat(%s)\n", gdk_atom_name(sSelTypes[format]));
#endif
/* when doing the selection_add_target, each case should have the same last parameter
which matches the case match */
switch(format)
{
case TARGET_TEXT_PLAIN:
// text/plain (default)
AddTarget(sSelTypes[format]);
// STRING (what X uses)
AddTarget(GDK_SELECTION_TYPE_STRING);
break;
case TARGET_TEXT_XIF:
// text/xif (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_TEXT_UNICODE:
// text/unicode (default)
AddTarget(sSelTypes[format]);
// UTF8 (what X uses)
AddTarget(sSelTypes[TARGET_UTF8]);
break;
case TARGET_TEXT_HTML:
// text/html (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_AOLMAIL:
// text/aolmail (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_IMAGE_PNG:
// image/png (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_IMAGE_JPEG:
// image/jpeg (default)
AddTarget(sSelTypes[format]);
break;
case TARGET_IMAGE_GIF:
// image/gif (default)
AddTarget(sSelTypes[format]);
break;
default:
// if we don't match something above, then just add it like its something we know about...
AddTarget(sSelTypes[format]);
}
}
PRBool nsClipboard::DoRealConvert(GdkAtom type)
{
#ifdef DEBUG_CLIPBOARD
g_print(" nsClipboard::DoRealConvert(%li)\n {\n", type);
#endif
int e = 0;
// Set a flag saying that we're blocking waiting for the callback:
mBlocking = PR_TRUE;
//
// ask X what kind of data we can get
//
#ifdef DEBUG_CLIPBOARD
g_print(" Doing real conversion of atom type '%s'\n", gdk_atom_name(type));
#endif
gtk_selection_convert(sWidget,
GDK_SELECTION_PRIMARY,
type,
GDK_CURRENT_TIME);
// Now we need to wait until the callback comes in ...
// i is in case we get a runaway (yuck).
#ifdef DEBUG_CLIPBOARD
printf(" Waiting for the callback... mBlocking = %d\n", mBlocking);
#endif /* DEBUG_CLIPBOARD */
for (e=0; mBlocking == PR_TRUE && e < 1000; ++e)
{
gtk_main_iteration_do(PR_TRUE);
}
#ifdef DEBUG_CLIPBOARD
g_print(" }\n");
#endif
if (mSelectionData.length > 0)
return PR_TRUE;
return PR_FALSE;
}
/* return PR_TRUE if we have converted or PR_FALSE if we havn't and need to keep being called */
PRBool nsClipboard::DoConvert(gint format)
{
#ifdef DEBUG_CLIPBOARD
g_print(" nsClipboard::DoConvert(%s)\n", gdk_atom_name(sSelTypes[format]));
#endif
/* when doing the selection_add_target, each case should have the same last parameter
which matches the case match */
PRBool r = PR_FALSE;
switch(format)
{
case TARGET_TEXT_PLAIN:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
r = DoRealConvert(GDK_SELECTION_TYPE_STRING);
if (r) return r;
break;
case TARGET_TEXT_XIF:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_TEXT_UNICODE:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
r = DoRealConvert(sSelTypes[TARGET_UTF8]);
if (r) return r;
break;
case TARGET_TEXT_HTML:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_AOLMAIL:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_IMAGE_PNG:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_IMAGE_JPEG:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
case TARGET_IMAGE_GIF:
r = DoRealConvert(sSelTypes[format]);
if (r) return r;
break;
default:
g_print("DoConvert called with bogus format\n");
}
return r;
}
//-------------------------------------------------------------------------
//
// The blocking Paste routine
//
//-------------------------------------------------------------------------
NS_IMETHODIMP
nsClipboard::GetNativeClipboardData(nsITransferable * aTransferable)
{
#ifdef DEBUG_CLIPBOARD
printf("nsClipboard::GetNativeClipboardData()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (nsnull == aTransferable) {
printf(" GetNativeClipboardData: Transferable is null!\n");
return NS_ERROR_FAILURE;
}
// get flavor list that includes all acceptable flavors (including ones obtained through
// conversion)
nsCOMPtr<nsISupportsArray> flavorList;
nsresult errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return NS_ERROR_FAILURE;
// Walk through flavors and see which flavor matches the one being pasted:
PRUint32 cnt;
flavorList->Count(&cnt);
nsCAutoString foundFlavor;
for ( PRUint32 i = 0; i < cnt; ++i ) {
nsCOMPtr<nsISupports> genericFlavor;
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericFlavor) );
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
gint format = GetFormat(flavorStr);
if (DoConvert(format)) {
foundFlavor = flavorStr;
break;
}
}
}
#ifdef DEBUG_CLIPBOARD
printf(" Got the callback: '%s', %d\n",
mSelectionData.data, mSelectionData.length);
#endif /* DEBUG_CLIPBOARD */
// We're back from the callback, no longer blocking:
mBlocking = PR_FALSE;
//
// Now we have data in mSelectionData.data.
// We just have to copy it to the transferable.
//
#if 0
// pinkerton - we have the flavor already from above, so we don't need
// to re-derrive it.
nsString *name = new nsString((const char*)gdk_atom_name(mSelectionData.type));
int format = GetFormat(*name);
df->SetString((const char*)gdk_atom_name(sSelTypes[format]));
#endif
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData ( foundFlavor, mSelectionData.data, mSelectionData.length, getter_AddRefs(genericDataWrapper) );
aTransferable->SetTransferData(foundFlavor,
genericDataWrapper,
mSelectionData.length);
//delete name;
// transferable is now copying the data, so we can free it.
// g_free(mSelectionData.data);
mSelectionData.data = nsnull;
mSelectionData.length = 0;
return NS_OK;
}
/**
* Called when the data from a paste comes in (recieved from gdk_selection_convert)
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aTime time the selection was requested
*/
void
nsClipboard::SelectionReceivedCB (GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
guint aTime)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionReceivedCB\n {\n");
#endif /* DEBUG_CLIPBOARD */
nsClipboard *cb =(nsClipboard *)gtk_object_get_data(GTK_OBJECT(aWidget),
"cb");
if (!cb)
{
g_print("no clipboard found.. this is bad.\n");
return;
}
cb->SelectionReceiver(aWidget, aSelectionData);
#ifdef DEBUG_CLIPBOARD
g_print(" }\n");
#endif
}
/**
* local method (called from nsClipboard::SelectionReceivedCB)
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
*/
void
nsClipboard::SelectionReceiver (GtkWidget *aWidget,
GtkSelectionData *aSD)
{
gint type;
mBlocking = PR_FALSE;
if (aSD->length < 0)
{
printf(" Error retrieving selection: length was %d\n",
aSD->length);
return;
}
type = TARGET_NONE;
for (int i=0; i < TARGET_LAST; i++)
{
if (sSelTypes[i] == aSD->type)
{
type = i;
break;
}
}
switch (type)
{
case GDK_TARGET_STRING:
case TARGET_UTF8:
case TARGET_TEXT_PLAIN:
case TARGET_TEXT_XIF:
case TARGET_TEXT_UNICODE:
case TARGET_TEXT_HTML:
#ifdef DEBUG_CLIPBOARD
g_print(" Copying mSelectionData pointer -- ");
#endif
mSelectionData = *aSD;
mSelectionData.data = g_new(guchar, aSD->length + 1);
#ifdef DEBUG_CLIPBOARD
g_print(" Data = %s\n Length = %i\n", aSD->data, aSD->length);
#endif
memcpy(mSelectionData.data,
aSD->data,
aSD->length);
// Null terminate in case anyone cares,
// and so we can print the string for debugging:
mSelectionData.data[aSD->length] = '\0';
mSelectionData.length = aSD->length;
return;
default:
mSelectionData = *aSD;
mSelectionData.data = g_new(guchar, aSD->length + 1);
memcpy(mSelectionData.data,
aSD->data,
aSD->length);
mSelectionData.length = aSD->length;
return;
}
}
/**
* Some platforms support deferred notification for putting data on the clipboard
* This method forces the data onto the clipboard in its various formats
* This may be used if the application going away.
*
* @result NS_OK if successful.
*/
NS_IMETHODIMP nsClipboard::ForceDataToClipboard()
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::ForceDataToClipboard()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (nsnull == mTransferable) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
nsClipboard::HasDataMatchingFlavors(nsISupportsArray* aFlavorList, PRBool * outResult)
{
*outResult = PR_TRUE; // say we always do.
return NS_OK;
}
/**
* This is the callback which is called when another app
* requests the selection.
*
* @param widget The widget
* @param aSelectionData Selection data
* @param info Value passed in from the callback init
* @param time Time when the selection request came in
*/
void nsClipboard::SelectionGetCB(GtkWidget *widget,
GtkSelectionData *aSelectionData,
guint aInfo,
guint aTime)
{
#ifdef DEBUG_CLIPBOARD
printf("nsClipboard::SelectionGetCB\n");
#endif /* DEBUG_CLIPBOARD */
nsClipboard *cb = (nsClipboard *)gtk_object_get_data(GTK_OBJECT(widget),
"cb");
void *clipboardData;
PRUint32 dataLength;
nsresult rv;
// Make sure we have a transferable:
if (!cb->mTransferable) {
printf("Clipboard has no transferable!\n");
return;
}
#ifdef DEBUG_CLIPBOARD
g_print(" aInfo == %d -", aInfo);
#endif
char* dataFlavor = nsnull;
// switch aInfo (atom) to our enum
int type = (int)aInfo;
for (int i=0; i < TARGET_LAST; i++)
{
if (sSelTypes[i] == aInfo)
{
type = i;
break;
}
}
switch(type)
{
case GDK_TARGET_STRING:
case TARGET_TEXT_PLAIN:
dataFlavor = kTextMime;
break;
case TARGET_TEXT_XIF:
dataFlavor = kXIFMime;
break;
case TARGET_TEXT_UNICODE:
case TARGET_UTF8:
dataFlavor = kUnicodeMime;
break;
case TARGET_TEXT_HTML:
dataFlavor = kHTMLMime;
break;
case TARGET_AOLMAIL:
dataFlavor = kAOLMailMime;
break;
case TARGET_IMAGE_PNG:
dataFlavor = kPNGImageMime;
break;
case TARGET_IMAGE_JPEG:
dataFlavor = kJPEGImageMime;
break;
case TARGET_IMAGE_GIF:
dataFlavor = kGIFImageMime;
break;
default:
{
/* handle outside things */
}
}
#ifdef DEBUG_CLIPBOARD
g_print("- aInfo is for %s\n", gdk_atom_name(aInfo));
#endif
// Get data out of transferable.
nsCOMPtr<nsISupports> genericDataWrapper;
rv = cb->mTransferable->GetTransferData(dataFlavor,
getter_AddRefs(genericDataWrapper),
&dataLength);
nsPrimitiveHelpers::CreateDataFromPrimitive ( dataFlavor, genericDataWrapper, &clipboardData, dataLength );
if (NS_SUCCEEDED(rv) && clipboardData && dataLength > 0) {
size_t size = 1;
// find the number of bytes in the data for the below thing
// size_t size = sizeof((void*)((unsigned char)clipboardData[0]));
// g_print("************ ***************** ******************* %i\n", size);
gtk_selection_data_set(aSelectionData,
aInfo, size*8,
(unsigned char *)clipboardData,
dataLength);
nsCRT::free ( NS_REINTERPRET_CAST(char*, clipboardData) );
}
else
printf("Transferable didn't support the data flavor\n");
}
/**
* Called when another app requests selection ownership
*
* @param aWidget the widget
* @param aEvent the GdkEvent for the selection
* @param aData value passed in from the callback init
*/
void nsClipboard::SelectionClearCB(GtkWidget *aWidget,
GdkEventSelection *aEvent,
gpointer aData)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionClearCB\n");
#endif /* DEBUG_CLIPBOARD */
nsClipboard *cb = (nsClipboard *)gtk_object_get_data(GTK_OBJECT(aWidget),
"cb");
cb->EmptyClipboard();
}
/**
* The routine called when another app asks for the content of the selection
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aData value passed in from the callback init
*/
void
nsClipboard::SelectionRequestCB (GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionRequestCB\n");
#endif /* DEBUG_CLIPBOARD */
}
/**
* ...
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aData value passed in from the callback init
*/
void
nsClipboard::SelectionNotifyCB (GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData)
{
#ifdef DEBUG_CLIPBOARD
printf(" nsClipboard::SelectionNotifyCB\n");
#endif /* DEBUG_CLIPBOARD */
}

View File

@@ -0,0 +1,132 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsClipboard_h__
#define nsClipboard_h__
#include "nsBaseClipboard.h"
#include <gtk/gtk.h>
#include <gtk/gtkinvisible.h>
class nsITransferable;
class nsIClipboardOwner;
class nsIWidget;
/**
* Native Gtk Clipboard wrapper
*/
class nsClipboard : public nsBaseClipboard
{
public:
nsClipboard();
virtual ~nsClipboard();
// nsIClipboard
NS_IMETHOD ForceDataToClipboard();
NS_IMETHOD HasDataMatchingFlavors(nsISupportsArray* aFlavorList, PRBool * outResult);
// invisible widget. also used by dragndrop
static GtkWidget *sWidget;
protected:
NS_IMETHOD SetNativeClipboardData();
NS_IMETHOD GetNativeClipboardData(nsITransferable * aTransferable);
PRBool mIgnoreEmptyNotification;
void AddTarget(GdkAtom aAtom);
gint GetFormat(const char* aMimeStr);
void RegisterFormat(gint format);
PRBool DoRealConvert(GdkAtom type);
PRBool DoConvert(gint format);
void Init(void);
// Used for communicating pasted data
// from the asynchronous X routines back to a blocking paste:
GtkSelectionData mSelectionData;
PRBool mBlocking;
void SelectionReceiver(GtkWidget *aWidget,
GtkSelectionData *aSD);
/**
* This is the callback which is called when another app
* requests the selection.
*
* @param widget The widget
* @param aSelectionData Selection data
* @param info Value passed in from the callback init
* @param time Time when the selection request came in
*/
static void SelectionGetCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
guint /*info*/,
guint /*time*/);
/**
* Called when another app requests selection ownership
*
* @param aWidget the widget
* @param aEvent the GdkEvent for the selection
* @param aData value passed in from the callback init
*/
static void SelectionClearCB(GtkWidget *aWidget,
GdkEventSelection *aEvent,
gpointer aData);
/**
* The routine called when another app asks for the content of the selection
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aData value passed in from the callback init
*/
static void SelectionRequestCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer data);
/**
* Called when the data from a paste comes in
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aTime time the selection was requested
*/
static void SelectionReceivedCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
guint aTime);
static void SelectionNotifyCB(GtkWidget *aWidget,
GtkSelectionData *aSelectionData,
gpointer aData);
};
#endif // nsClipboard_h__

View File

@@ -0,0 +1,357 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsComboBox.h"
#include "nsGUIEvent.h"
#include "nsString.h"
#define DBG 0
#define INITIAL_MAX_ITEMS 128
#define ITEMS_GROWSIZE 128
NS_IMPL_ADDREF_INHERITED(nsComboBox, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsComboBox, nsWidget)
NS_IMPL_QUERY_INTERFACE3(nsComboBox, nsIComboBox, nsIListWidget, nsIWidget)
//-------------------------------------------------------------------------
//
// nsComboBox constructor
//
//-------------------------------------------------------------------------
nsComboBox::nsComboBox() : nsWidget(), nsIListWidget(), nsIComboBox()
{
NS_INIT_REFCNT();
mMultiSelect = PR_FALSE;
mItems = nsnull;
mNumItems = 0;
}
//-------------------------------------------------------------------------
//
// nsComboBox:: destructor
//
//-------------------------------------------------------------------------
nsComboBox::~nsComboBox()
{
if (mItems) {
for (GList *items = mItems; items; items = (GList*) g_list_next(items)){
g_free(items->data);
}
g_list_free(mItems);
}
gtk_widget_destroy(mCombo);
}
void nsComboBox::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mWidget);
InstallButtonReleaseSignal(mWidget);
InstallEnterNotifySignal(mWidget);
InstallLeaveNotifySignal(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
}
//-------------------------------------------------------------------------
//
// initializer
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::SetMultipleSelection(PRBool aMultipleSelections)
{
mMultiSelect = aMultipleSelections;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// AddItemAt
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::AddItemAt(nsString &aItem, PRInt32 aPosition)
{
NS_ALLOC_STR_BUF(val, aItem, 256);
mItems = g_list_insert( mItems, g_strdup(val), aPosition );
mNumItems++;
if (mCombo) {
gtk_combo_set_popdown_strings( GTK_COMBO( mCombo ), mItems );
}
NS_FREE_STR_BUF(val);
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Finds an item at a postion
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::FindItem(nsString &aItem, PRInt32 aStartPos)
{
NS_ALLOC_STR_BUF(val, aItem, 256);
int i;
PRInt32 inx = -1;
GList *items = g_list_nth(mItems, aStartPos);
for(i=0; items != NULL; items = (GList *) g_list_next(items), i++ )
{
if(!strcmp(val, (gchar *) items->data))
{
inx = i;
break;
}
}
NS_FREE_STR_BUF(val);
return inx;
}
//-------------------------------------------------------------------------
//
// CountItems - Get Item Count
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::GetItemCount()
{
return (PRInt32)mNumItems;
}
//-------------------------------------------------------------------------
//
// Removes an Item at a specified location
//
//-------------------------------------------------------------------------
PRBool nsComboBox::RemoveItemAt(PRInt32 aPosition)
{
if (aPosition >= 0 && aPosition < mNumItems) {
g_free(g_list_nth(mItems, aPosition)->data);
mItems = g_list_remove_link(mItems, g_list_nth(mItems, aPosition));
mNumItems--;
if (mCombo) {
gtk_combo_set_popdown_strings(GTK_COMBO( mCombo ), mItems);
}
return PR_TRUE;
}
else
return PR_FALSE;
}
//-------------------------------------------------------------------------
//
// Removes an Item at a specified location
//
//-------------------------------------------------------------------------
PRBool nsComboBox::GetItemAt(nsString& anItem, PRInt32 aPosition)
{
if (aPosition >= 0 && aPosition < mNumItems) {
anItem = (gchar *) g_list_nth(mItems, aPosition)->data;
return PR_TRUE;
}
return PR_FALSE;
}
//-------------------------------------------------------------------------
//
// Gets the selected of selected item
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::GetSelectedItem(nsString& aItem)
{
aItem.Truncate();
if (mCombo) {
aItem = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO(mCombo)->entry));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Gets the list of selected otems
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::GetSelectedIndex()
{
nsString nsstring;
GetSelectedItem(nsstring);
return FindItem(nsstring, 0);
}
//-------------------------------------------------------------------------
//
// SelectItem
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::SelectItem(PRInt32 aPosition)
{
GList *pos;
if (!mItems)
return NS_ERROR_FAILURE;
pos = g_list_nth(mItems, aPosition);
if (!pos)
return NS_ERROR_FAILURE;
if (mCombo) {
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(mCombo)->entry),
(gchar *) pos->data);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// GetSelectedCount
//
//-------------------------------------------------------------------------
PRInt32 nsComboBox::GetSelectedCount()
{
if (!mMultiSelect) {
PRInt32 inx = GetSelectedIndex();
return (inx == -1? 0 : 1);
} else {
return 0;
}
}
//-------------------------------------------------------------------------
//
// GetSelectedIndices
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
{
// this is an error
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// Deselect
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::Deselect()
{
if (mMultiSelect) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Create the native GtkCombo widget
//
//-------------------------------------------------------------------------
NS_METHOD nsComboBox::CreateNative(GtkObject *parentWindow)
{
mWidget = ::gtk_event_box_new();
::gtk_widget_set_name(mWidget, "nsComboBox");
mCombo = ::gtk_combo_new();
gtk_widget_show(mCombo);
/* make the stuff uneditable */
gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(mCombo)->entry), PR_FALSE);
gtk_signal_connect(GTK_OBJECT(mCombo),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
gtk_signal_connect(GTK_OBJECT(GTK_COMBO(mCombo)->popwin),
"unmap",
GTK_SIGNAL_FUNC(UnmapSignal),
this);
gtk_container_add(GTK_CONTAINER(mWidget), mCombo);
return NS_OK;
}
void
nsComboBox::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mCombo) {
mCombo = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
gint
nsComboBox::UnmapSignal(GtkWidget* aGtkWidget, nsComboBox* aCombo)
{
if (!aCombo) return PR_FALSE;
aCombo->OnUnmapSignal(aGtkWidget);
return PR_TRUE;
}
void
nsComboBox::OnUnmapSignal(GtkWidget * aWidget)
{
if (!aWidget) return;
// Generate a NS_CONTROL_CHANGE event and send it to the frame
nsGUIEvent event;
event.eventStructType = NS_GUI_EVENT;
nsPoint point(0,0);
InitEvent(event, NS_CONTROL_CHANGE, &point);
DispatchWindowEvent(&event);
}
//-------------------------------------------------------------------------
//
// Get handle for style
//
//-------------------------------------------------------------------------
/*virtual*/
void nsComboBox::SetFontNative(GdkFont *aFont)
{
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
// gtk_style_copy ups the ref count of the font
gdk_font_unref (style->font);
style->font = aFont;
gdk_font_ref(style->font);
gtk_widget_set_style(GTK_BIN (mWidget)->child, style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsComboBox_h__
#define nsComboBox_h__
#include "nsWidget.h"
#include "nsIComboBox.h"
/**
* Native GTK+ Listbox wrapper
*/
class nsComboBox : public nsWidget,
public nsIListWidget,
public nsIComboBox
{
public:
nsComboBox();
virtual ~nsComboBox();
NS_DECL_ISUPPORTS_INHERITED
// nsIComboBox interface
NS_IMETHOD AddItemAt(nsString &aItem, PRInt32 aPosition);
virtual PRInt32 FindItem(nsString &aItem, PRInt32 aStartPos);
virtual PRInt32 GetItemCount();
virtual PRBool RemoveItemAt(PRInt32 aPosition);
virtual PRBool GetItemAt(nsString& anItem, PRInt32 aPosition);
NS_IMETHOD GetSelectedItem(nsString& aItem);
virtual PRInt32 GetSelectedIndex();
NS_IMETHOD SelectItem(PRInt32 aPosition);
NS_IMETHOD Deselect() ;
// nsIComboBox interface
NS_IMETHOD SetMultipleSelection(PRBool aMultipleSelections);
PRInt32 GetSelectedCount();
NS_IMETHOD GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
virtual void SetFontNative(GdkFont *aFont);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
virtual void OnUnmapSignal(GtkWidget* aWidget);
static gint UnmapSignal(GtkWidget* aGtkWidget, nsComboBox* aCombo);
GtkWidget *mCombo; /* workaround for gtkcombo bug */
GList *mItems;
PRBool mMultiSelect;
int mNumItems;
};
#endif // nsComboBox_h__

View File

@@ -0,0 +1,744 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsContextMenu.h"
#include "nsIComponentManager.h"
#include "nsIDOMElement.h"
#include "nsIDOMNode.h"
#include "nsIMenuBar.h"
#include "nsIMenuItem.h"
#include "nsIMenuListener.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
//-------------------------------------------------------------------------
nsresult nsContextMenu::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenu::GetIID())) {
*aInstancePtr = (void*)(nsIMenu*) this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*)(nsISupports*)(nsIMenu*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIMenuListener::GetIID())) {
*aInstancePtr = (void*)(nsIMenuListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
//-------------------------------------------------------------------------
NS_IMPL_ADDREF(nsContextMenu)
NS_IMPL_RELEASE(nsContextMenu)
//-------------------------------------------------------------------------
//
// nsContextMenu constructor
//
//-------------------------------------------------------------------------
nsContextMenu::nsContextMenu()
{
NS_INIT_REFCNT();
mNumMenuItems = 0;
mMenu = nsnull;
mParent = nsnull;
mListener = nsnull;
mConstructCalled = PR_FALSE;
mDOMNode = nsnull;
mWebShell = nsnull;
mDOMElement = nsnull;
mAlignment = "topleft";
mAnchorAlignment = "none";
}
//-------------------------------------------------------------------------
//
// nsContextMenu destructor
//
//-------------------------------------------------------------------------
nsContextMenu::~nsContextMenu()
{
}
//-------------------------------------------------------------------------
//
// Create the proper widget
//
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::Create(nsISupports *aParent,
const nsString& anAlignment,
const nsString& anAnchorAlignment)
{
if(aParent)
{
nsIWidget *parent = nsnull;
aParent->QueryInterface(nsIWidget::GetIID(), (void**) &parent);
if(parent)
{
mParent = parent;
NS_RELEASE(parent);
}
}
mAlignment = anAlignment;
mAnchorAlignment = anAnchorAlignment;
mMenu = gtk_menu_new();
gtk_signal_connect (GTK_OBJECT (mMenu), "map",
GTK_SIGNAL_FUNC(menu_map_handler),
this);
gtk_signal_connect (GTK_OBJECT (mMenu), "unmap",
GTK_SIGNAL_FUNC(menu_unmap_handler),
this);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::GetParent(nsISupports*& aParent)
{
aParent = nsnull;
if (nsnull != mParent) {
return mParent->QueryInterface(kISupportsIID,
(void**)&aParent);
}
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddItem(nsISupports * aItem)
{
if(aItem)
{
nsIMenuItem * menuitem = nsnull;
aItem->QueryInterface(nsIMenuItem::GetIID(),
(void**)&menuitem);
if(menuitem)
{
AddMenuItem(menuitem); // nsMenu now owns this
NS_RELEASE(menuitem);
}
else
{
nsIMenu * menu = nsnull;
aItem->QueryInterface(nsIMenu::GetIID(),
(void**)&menu);
if(menu)
{
AddMenu(menu); // nsMenu now owns this
NS_RELEASE(menu);
}
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddMenuItem(nsIMenuItem * aMenuItem)
{
GtkWidget *widget;
void *voidData;
aMenuItem->GetNativeData(voidData);
widget = GTK_WIDGET(voidData);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
// XXX add aMenuItem to internal data structor list
// Need to be adding an nsISupports *, not nsIMenuItem *
nsISupports * supports = nsnull;
aMenuItem->QueryInterface(kISupportsIID,
(void**)&supports);
{
mMenuItemVoidArray.AppendElement(supports);
mNumMenuItems++;
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddMenu(nsIMenu * aMenu)
{
nsString Label;
GtkWidget *newmenu=nsnull;
char *labelStr;
void *voidData=NULL;
aMenu->GetLabel(Label);
labelStr = Label.ToNewCString();
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
nsnull,
nsIMenuItem::GetIID(),
(void**)&pnsMenuItem);
if (NS_OK == rv) {
nsISupports * supports = nsnull;
QueryInterface(kISupportsIID, (void**) &supports);
pnsMenuItem->Create(supports, labelStr, PR_FALSE); //PR_TRUE);
NS_RELEASE(supports);
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
void * menuitem = nsnull;
pnsMenuItem->GetNativeData(menuitem);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), newmenu);
NS_RELEASE(pnsMenuItem);
}
nsCRT::free(labelStr);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddSeparator()
{
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(
kMenuItemCID, nsnull, nsIMenuItem::GetIID(), (void**)&pnsMenuItem);
if (NS_OK == rv) {
nsString tmp = "separator";
nsISupports * supports = nsnull;
QueryInterface(kISupportsIID, (void**) &supports);
pnsMenuItem->Create(supports, tmp, PR_TRUE);
NS_RELEASE(supports);
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
NS_RELEASE(pnsMenuItem);
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::GetItemCount(PRUint32 &aCount)
{
// this should be right.. does it need to be +1 ?
aCount = g_list_length(GTK_MENU_SHELL(mMenu)->children);
//g_print("nsMenu::GetItemCount = %i\n", aCount);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::GetItemAt(const PRUint32 aCount, nsISupports *& aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::InsertItemAt(const PRUint32 aCount, nsISupports * aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::InsertSeparator(const PRUint32 aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::RemoveItem(const PRUint32 aCount)
{
#if 0
// this may work here better than Removeall(), but i'm not sure how to test this one
nsISupports *item = mMenuItemVoidArray[aPos];
delete item;
mMenuItemVoidArray.RemoveElementAt(aPos);
#endif
/*
gtk_menu_shell_remove (GTK_MENU_SHELL (mMenu), item);
nsCRT::free(labelStr);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
*/
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::RemoveAll()
{
//g_print("nsMenu::RemoveAll()\n");
#undef DEBUG_pavlov
#ifdef DEBUG_pavlov
// this doesn't work quite right, but this is about all that should really be needed
int i=0;
nsIMenu *menu = nsnull;
nsIMenuItem *menuitem = nsnull;
nsISupports *item = nsnull;
for (i=mMenuItemVoidArray.Count(); i>0; i--)
{
item = (nsISupports*)mMenuItemVoidArray[i-1];
if(nsnull != item)
{
if (NS_OK == item->QueryInterface(nsIMenuItem::GetIID(), (void**)&menuitem))
{
// we do this twice because we have to do it once for QueryInterface,
// then we want to get rid of it.
// g_print("remove nsMenuItem\n");
NS_RELEASE(menuitem);
NS_RELEASE(item);
menuitem = nsnull;
} else if (NS_OK == item->QueryInterface(nsIMenu::GetIID(), (void**)&menu)) {
#ifdef NOISY_MENUS
g_print("remove nsMenu\n");
#endif
NS_RELEASE(menu);
NS_RELEASE(item);
menu = nsnull;
}
// mMenuItemVoidArray.RemoveElementAt(i-1);
}
}
mMenuItemVoidArray.Clear();
return NS_OK;
#else
for (int i = mMenuItemVoidArray.Count(); i > 0; i--) {
if(nsnull != mMenuItemVoidArray[i-1]) {
nsIMenuItem * menuitem = nsnull;
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenuItem::GetIID(),
(void**)&menuitem);
if(menuitem) {
void *gtkmenuitem = nsnull;
menuitem->GetNativeData(gtkmenuitem);
if (gtkmenuitem) {
gtk_widget_ref(GTK_WIDGET(gtkmenuitem));
//gtk_widget_destroy(GTK_WIDGET(gtkmenuitem));
g_print("%p, %p\n",
GTK_WIDGET(GTK_CONTAINER(GTK_MENU_SHELL(GTK_MENU(mMenu)))),
GTK_WIDGET(GTK_WIDGET(gtkmenuitem)->parent));
gtk_container_remove(GTK_CONTAINER(GTK_MENU_SHELL(GTK_MENU(mMenu))),
GTK_WIDGET(gtkmenuitem));
}
} else {
nsIMenu * menu= nsnull;
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(),
(void**)&menu);
if(menu)
{
void * gtkmenu = nsnull;
menu->GetNativeData(&gtkmenu);
if(gtkmenu){
g_print("nsMenu::RemoveAll() trying to remove nsMenu");
//gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
}
}
}
}
}
//g_print("end RemoveAll\n");
return NS_OK;
#endif
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::GetNativeData(void ** aData)
{
*aData = (void *)mMenu;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::AddMenuListener(nsIMenuListener * aMenuListener)
{
mListener = aMenuListener;
NS_ADDREF(mListener);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::RemoveMenuListener(nsIMenuListener * aMenuListener)
{
if (aMenuListener == mListener) {
NS_IF_RELEASE(mListener);
}
return NS_OK;
}
//-------------------------------------------------------------------------
// nsIMenuListener interface
//-------------------------------------------------------------------------
nsEventStatus nsContextMenu::MenuItemSelected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuSelected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
void menu_popup_position(GtkMenu *menu,
gint *x,
gint *y,
gpointer data)
{
nsContextMenu *cm = (nsContextMenu*)data;
*x = cm->GetX();
*y = cm->GetY();
}
nsEventStatus nsContextMenu::MenuSelected(const nsMenuEvent & aMenuEvent)
{
MenuConstruct(aMenuEvent,
mParent,
mDOMNode,
mWebShell);
//GtkWidget *parent = GTK_WIDGET(mParent->GetNativeData(NS_NATIVE_WIDGET));
gtk_menu_popup (GTK_MENU(mMenu),
(GtkWidget*)nsnull, (GtkWidget*)nsnull,
menu_popup_position,
this, 1, GDK_CURRENT_TIME);
/*
if (nsnull != mListener) {
mListener->MenuSelected(aMenuEvent);
}
*/
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsIMenuItem * nsContextMenu::FindMenuItem(nsIContextMenu * aMenu, PRUint32 aId)
{
return nsnull;
}
//-------------------------------------------------------------------------
nsEventStatus nsContextMenu::MenuDeselected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuDeselected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsContextMenu::MenuConstruct(const nsMenuEvent &aMenuEvent,
nsIWidget *aParentWindow,
void *menuNode,
void *aWebShell)
{
//g_print("nsMenu::MenuConstruct called \n");
if(menuNode){
SetDOMNode((nsIDOMNode*)menuNode);
}
if(!aWebShell){
aWebShell = mWebShell;
}
// First open the menu.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->SetAttribute("open", "true");
// Begin menuitem inner loop
nsCOMPtr<nsIDOMNode> menuitemNode;
((nsIDOMNode*)mDOMNode)->GetFirstChild(getter_AddRefs(menuitemNode));
unsigned short menuIndex = 0;
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
nsString menuitemName;
menuitemElement->GetNodeName(menuitemNodeType);
if (menuitemNodeType.Equals("menuitem")) {
// LoadMenuItem
LoadMenuItem(this,
menuitemElement,
menuitemNode,
menuIndex,
(nsIWebShell*)aWebShell);
} else if (menuitemNodeType.Equals("separator")) {
AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Load a submenu
LoadSubMenu(this, menuitemElement, menuitemNode);
}
}
++menuIndex;
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsContextMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
{
// Close the node.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->RemoveAttribute("open");
//g_print("nsMenu::MenuDestruct called \n");
mConstructCalled = PR_FALSE;
RemoveAll();
return nsEventStatus_eIgnore;
}
//----------------------------------------
void nsContextMenu::LoadMenuItem(nsIMenu *pParentMenu,
nsIDOMElement *menuitemElement,
nsIDOMNode *menuitemNode,
unsigned short menuitemIndex,
nsIWebShell *aWebShell)
{
static const char* NS_STRING_TRUE = "true";
nsString disabled;
nsString menuitemName;
nsString menuitemCmd;
menuitemElement->GetAttribute(nsAutoString("disabled"), disabled);
menuitemElement->GetAttribute(nsAutoString("name"), menuitemName);
menuitemElement->GetAttribute(nsAutoString("cmd"), menuitemCmd);
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
nsnull,
nsIMenuItem::GetIID(),
(void**)&pnsMenuItem);
if (NS_OK == rv) {
pnsMenuItem->Create(pParentMenu, menuitemName, PR_FALSE);
nsISupports * supports = nsnull;
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
if(disabled == NS_STRING_TRUE) {
pnsMenuItem->SetEnabled(PR_FALSE);
}
// Create MenuDelegate - this is the intermediator inbetween
// the DOM node and the nsIMenuItem
// The nsWebShellWindow wacthes for Document changes and then notifies the
// the appropriate nsMenuDelegate object
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
if (!domElement) {
//return NS_ERROR_FAILURE;
return;
}
nsAutoString cmdAtom("onclick");
nsString cmdName;
domElement->GetAttribute(cmdAtom, cmdName);
pnsMenuItem->SetCommand(cmdName);
// DO NOT use passed in webshell because of messed up windows dynamic loading
// code.
pnsMenuItem->SetWebShell(mWebShell);
pnsMenuItem->SetDOMElement(domElement);
NS_RELEASE(pnsMenuItem);
}
return;
}
//----------------------------------------
void nsContextMenu::LoadSubMenu(nsIMenu *pParentMenu,
nsIDOMElement *menuElement,
nsIDOMNode *menuNode)
{
nsString menuName;
menuElement->GetAttribute(nsAutoString("name"), menuName);
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
// Create nsMenu
nsIMenu * pnsMenu = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuCID,
nsnull,
nsIMenu::GetIID(),
(void**)&pnsMenu);
if (NS_OK == rv) {
// Call Create
nsISupports * supports = nsnull;
pParentMenu->QueryInterface(kISupportsIID, (void**) &supports);
pnsMenu->Create(supports, menuName);
NS_RELEASE(supports); // Balance QI
// Set nsMenu Name
pnsMenu->SetLabel(menuName);
supports = nsnull;
pnsMenu->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports); // parent takes ownership
NS_RELEASE(supports);
pnsMenu->SetWebShell(mWebShell);
pnsMenu->SetDOMNode(menuNode);
/*
// Begin menuitem inner loop
unsigned short menuIndex = 0;
nsCOMPtr<nsIDOMNode> menuitemNode;
menuNode->GetFirstChild(getter_AddRefs(menuitemNode));
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
menuitemElement->GetNodeName(menuitemNodeType);
#ifdef DEBUG_saari
printf("Type [%s] %d\n", menuitemNodeType.ToNewCString(), menuitemNodeType.Equals("separator"));
#endif
if (menuitemNodeType.Equals("menuitem")) {
// Load a menuitem
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode, menuIndex, mWebShell);
} else if (menuitemNodeType.Equals("separator")) {
pnsMenu->AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Add a submenu
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
}
}
++menuIndex;
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
*/
}
}
//----------------------------------------
void nsContextMenu::LoadMenuItem(nsIContextMenu *pParentMenu,
nsIDOMElement *menuitemElement,
nsIDOMNode *menuitemNode,
unsigned short menuitemIndex,
nsIWebShell *aWebShell)
{
}
//----------------------------------------
void nsContextMenu::LoadSubMenu(nsIContextMenu *pParentMenu,
nsIDOMElement *menuElement,
nsIDOMNode *menuNode)
{
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::SetLocation(PRInt32 aX, PRInt32 aY)
{
mX = aX;
mY = aY;
return NS_OK;
}
// local methods
gint nsContextMenu::GetX(void)
{
return mX;
}
gint nsContextMenu::GetY(void)
{
return mY;
}
// end silly local methods
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::SetDOMNode(nsIDOMNode *aMenuNode)
{
mDOMNode = aMenuNode;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::SetDOMElement(nsIDOMElement *aMenuElement)
{
mDOMElement = aMenuElement;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsContextMenu::SetWebShell(nsIWebShell *aWebShell)
{
mWebShell = aWebShell;
return NS_OK;
}

View File

@@ -0,0 +1,139 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsContextMenu_h__
#define nsContextMenu_h__
#include "nsIContextMenu.h"
#include "nsISupportsArray.h"
#include "nsVoidArray.h"
#include "nsIDOMElement.h"
#include "nsIWebShell.h"
class nsIMenuListener;
/**
* Native Win32 button wrapper
*/
class nsContextMenu : public nsIContextMenu, public nsIMenuListener
{
public:
nsContextMenu();
virtual ~nsContextMenu();
NS_DECL_ISUPPORTS
//nsIMenuListener interface
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menubarNode,
void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
// nsIMenu Methods
NS_IMETHOD Create(nsISupports * aParent,
const nsString& anAlignment,
const nsString& aAnchorAlign);
NS_IMETHOD GetParent(nsISupports *&aParent);
NS_IMETHOD AddItem(nsISupports * aItem);
NS_IMETHOD AddSeparator();
NS_IMETHOD GetItemCount(PRUint32 &aCount);
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
NS_IMETHOD RemoveItem(const PRUint32 aPos);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void** aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
//
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD InsertSeparator(const PRUint32 aCount);
NS_IMETHOD SetDOMNode(nsIDOMNode * menuNode);
NS_IMETHOD SetDOMElement(nsIDOMElement * menuElement);
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
NS_IMETHOD SetLocation(PRInt32 aX, PRInt32 aY);
gint GetX(void);
gint GetY(void);
protected:
nsIMenuBar * GetMenuBar(nsIMenu * aMenu);
nsIWidget * GetParentWidget();
char* GetACPString(nsString& aStr);
void LoadMenuItem(nsIMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode,
unsigned short menuitemIndex,
nsIWebShell * aWebShell);
void LoadSubMenu(nsIMenu * pParentMenu,
nsIDOMElement * menuElement,
nsIDOMNode * menuNode);
void LoadMenuItem(nsIContextMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode,
unsigned short menuitemIndex,
nsIWebShell * aWebShell);
void LoadSubMenu(nsIContextMenu * pParentMenu,
nsIDOMElement * menuElement,
nsIDOMNode * menuNode);
nsIMenuItem * FindMenuItem(nsIContextMenu * aMenu, PRUint32 aId);
nsString mLabel;
PRUint32 mNumMenuItems;
GtkWidget *mMenu;
nsVoidArray mMenuItemVoidArray;
nsIWidget *mParent;
nsIMenuListener * mListener;
PRBool mConstructCalled;
nsIDOMNode * mDOMNode;
nsIWebShell * mWebShell;
nsIDOMElement * mDOMElement;
nsString mAlignment;
nsString mAnchorAlignment;
PRInt32 mX;
PRInt32 mY;
};
#endif // nsContextMenu_h__

View File

@@ -0,0 +1,592 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsDragService.h"
#include "nsITransferable.h"
#include "nsString.h"
#include "nsClipboard.h"
#include "nsIRegion.h"
#include "nsVoidArray.h"
#include "nsISupportsPrimitives.h"
#include "nsPrimitiveHelpers.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsWidgetsCID.h"
NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
NS_IMPL_QUERY_INTERFACE2(nsDragService, nsIDragService, nsIDragSession)
#define DEBUG_DRAG 1
//-------------------------------------------------------------------------
//
// DragService constructor
//
//-------------------------------------------------------------------------
nsDragService::nsDragService()
{
NS_INIT_REFCNT();
mWidget = nsnull;
mNumFlavors = 0;
}
//-------------------------------------------------------------------------
//
// DragService destructor
//
//-------------------------------------------------------------------------
nsDragService::~nsDragService()
{
}
enum {
TARGET_STRING,
TARGET_ROOTWIN
};
static GtkTargetEntry target_table[] = {
{ "STRING", 0, TARGET_STRING },
{ "text/plain", 0, TARGET_STRING },
{ "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
};
static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
NS_IMETHODIMP nsDragService::StartDragSession()
{
printf("nsDragService::StartDragSession()\n");
nsBaseDragService::StartDragSession();
/*
gtk_drag_source_set(mWidget,
GDK_MODIFIER_MASK,
targetlist,
mNumFlavors,
action);
*/
gtk_drag_source_set(mWidget,
GDK_MODIFIER_MASK,
target_table,
n_targets,
mActionType);
return NS_OK;
}
NS_IMETHODIMP nsDragService::EndDragSession()
{
printf("nsDragService::EndDragSession()\n");
nsBaseDragService::EndDragSession();
gtk_drag_source_unset(mWidget);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::InvokeDragSession (nsISupportsArray *aTransferableArray,
nsIScriptableRegion *aRegion,
PRUint32 aActionType)
{
mWidget = gtk_get_event_widget(gtk_get_current_event());
// add the flavors from the transferables. Cache this array for the send data proc
GtkTargetList *targetlist = RegisterDragItemsAndFlavors(aTransferableArray);
switch (aActionType)
{
case DRAGDROP_ACTION_NONE:
mActionType = GDK_ACTION_DEFAULT;
break;
case DRAGDROP_ACTION_COPY:
mActionType = GDK_ACTION_COPY;
break;
case DRAGDROP_ACTION_MOVE:
mActionType = GDK_ACTION_MOVE;
break;
case DRAGDROP_ACTION_LINK:
mActionType = GDK_ACTION_LINK;
break;
}
StartDragSession();
// XXX 3rd param ??? & last param should be a real event...
gtk_drag_begin(mWidget, targetlist, mActionType, 1, gtk_get_current_event());
#if 0
// we have to synthesize the native event because we may be called from JavaScript
// through XPConnect. In that case, we only have a DOM event and no way to
// get to the native event. As a consequence, we just always fake it.
Point globalMouseLoc;
::GetMouse(&globalMouseLoc);
::LocalToGlobal(&globalMouseLoc);
WindowPtr theWindow = nsnull;
if ( ::FindWindow(globalMouseLoc, &theWindow) != inContent ) {
// debugging sanity check
#ifdef NS_DEBUG
DebugStr("\pAbout to start drag, but FindWindow() != inContent; g");
#endif
}
EventRecord theEvent;
theEvent.what = mouseDown;
theEvent.message = reinterpret_cast<UInt32>(theWindow);
theEvent.when = 0;
theEvent.where = globalMouseLoc;
theEvent.modifiers = 0;
RgnHandle theDragRgn = ::NewRgn();
BuildDragRegion ( aDragRgn, globalMouseLoc, theDragRgn );
// register drag send proc which will call us back when asked for the actual
// flavor data (instead of placing it all into the drag manager)
::SetDragSendProc ( theDragRef, sDragSendDataUPP, this );
// start the drag. Be careful, mDragRef will be invalid AFTER this call (it is
// reset by the dragTrackingHandler).
::TrackDrag ( theDragRef, &theEvent, theDragRgn );
// clean up after ourselves
::DisposeRgn ( theDragRgn );
result = ::DisposeDrag ( theDragRef );
NS_ASSERTION ( result == noErr, "Error disposing drag" );
mDragRef = 0L;
mDataItems = nsnull;
return NS_OK;
#endif
return NS_OK;
}
GtkTargetList *
nsDragService::RegisterDragItemsAndFlavors(nsISupportsArray *inArray)
{
unsigned int numDragItems = 0;
inArray->Count(&numDragItems);
GtkTargetList *targetlist;
targetlist = gtk_target_list_new(nsnull, numDragItems);
for (unsigned int i = 0; i < numDragItems; ++i)
{
nsCOMPtr<nsISupports> genericItem;
inArray->GetElementAt (i, getter_AddRefs(genericItem));
nsCOMPtr<nsITransferable> currItem (do_QueryInterface(genericItem));
if (currItem)
{
nsCOMPtr<nsISupportsArray> flavorList;
if (NS_SUCCEEDED(currItem->FlavorsTransferableCanExport(getter_AddRefs(flavorList))))
{
flavorList->Count (&mNumFlavors);
for (PRUint32 flavorIndex = 0; flavorIndex < mNumFlavors; ++flavorIndex)
{
nsCOMPtr<nsISupports> genericWrapper;
flavorList->GetElementAt ( flavorIndex, getter_AddRefs(genericWrapper) );
nsCOMPtr<nsISupportsString> currentFlavor ( do_QueryInterface(genericWrapper) );
if ( currentFlavor )
{
nsXPIDLCString flavorStr;
currentFlavor->ToString ( getter_Copies(flavorStr) );
// register native flavors
GdkAtom atom = gdk_atom_intern(flavorStr, PR_TRUE);
gtk_target_list_add(targetlist, atom, 1, atom);
}
} // foreach flavor in item
} // if valid flavor list
} // if item is a transferable
} // foreach drag item
return targetlist;
}
/* return PR_TRUE if we have converted or PR_FALSE if we havn't and need to keep being called */
PRBool nsDragService::DoConvert(GdkAtom type)
{
#ifdef DEBUG_DRAG
g_print(" nsDragService::DoRealConvert(%li)\n {\n", type);
#endif
int e = 0;
// Set a flag saying that we're blocking waiting for the callback:
mBlocking = PR_TRUE;
//
// ask X what kind of data we can get
//
#ifdef DEBUG_DRAG
g_print(" Doing real conversion of atom type '%s'\n", gdk_atom_name(type));
#endif
gtk_selection_convert(mWidget,
GDK_SELECTION_PRIMARY,
type,
GDK_CURRENT_TIME);
// Now we need to wait until the callback comes in ...
// i is in case we get a runaway (yuck).
#ifdef DEBUG_DRAG
printf(" Waiting for the callback... mBlocking = %d\n", mBlocking);
#endif /* DEBUG_CLIPBOARD */
for (e=0; mBlocking == PR_TRUE && e < 1000; ++e)
{
gtk_main_iteration_do(PR_TRUE);
}
#ifdef DEBUG_DRAG
g_print(" }\n");
#endif
if (mSelectionData.length > 0)
return PR_TRUE;
return PR_FALSE;
}
#if 0
/**
* Called when the data from a drag comes in (recieved from gdk_selection_convert)
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
* @param aTime time the selection was requested
*/
void
nsDragService::SelectionReceivedCB (GtkWidget *aWidget,
GdkDragContext *aContext,
gint aX,
gint aY,
GtkSelectionData *aSelectionData,
guint aInfo,
guint aTime)
{
#ifdef DEBUG_DRAG
printf(" nsDragService::SelectionReceivedCB\n {\n");
#endif
nsDragService *ds =(nsDragSession *)gtk_object_get_data(GTK_OBJECT(aWidget),
"ds");
if (!cb)
{
g_print("no dragservice found.. this is bad.\n");
return;
}
ds->SelectionReceiver(aWidget, aSelectionData);
#ifdef DEBUG_DRAG
g_print(" }\n");
#endif
}
/**
* local method (called from nsClipboard::SelectionReceivedCB)
*
* @param aWidget the widget
* @param aSelectionData gtk selection stuff
*/
void
nsDragService::SelectionReceiver (GtkWidget *aWidget,
GtkSelectionData *aSD)
{
gint type;
mBlocking = PR_FALSE;
if (aSD->length < 0)
{
printf(" Error retrieving selection: length was %d\n",
aSD->length);
return;
}
switch (type)
{
case GDK_TARGET_STRING:
case TARGET_COMPOUND_TEXT:
case TARGET_TEXT_PLAIN:
case TARGET_TEXT_XIF:
case TARGET_TEXT_UNICODE:
case TARGET_TEXT_HTML:
#ifdef DEBUG_CLIPBOARD
g_print(" Copying mSelectionData pointer -- ");
#endif
mSelectionData = *aSD;
mSelectionData.data = g_new(guchar, aSD->length + 1);
#ifdef DEBUG_CLIPBOARD
g_print(" Data = %s\n Length = %i\n", aSD->data, aSD->length);
#endif
memcpy(mSelectionData.data,
aSD->data,
aSD->length);
// Null terminate in case anyone cares,
// and so we can print the string for debugging:
mSelectionData.data[aSD->length] = '\0';
mSelectionData.length = aSD->length;
return;
default:
mSelectionData = *aSD;
mSelectionData.data = g_new(guchar, aSD->length + 1);
memcpy(mSelectionData.data,
aSD->data,
aSD->length);
mSelectionData.length = aSD->length;
return;
}
}
#endif
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetNumDropItems (PRUint32 * aNumItems)
{
*aNumItems = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetData (nsITransferable * aTransferable, PRUint32 anItem)
{
#ifdef DEBUG_DRAG
printf("nsClipboard::GetNativeClipboardData()\n");
#endif /* DEBUG_CLIPBOARD */
// make sure we have a good transferable
if (!aTransferable) {
printf(" GetData: Transferable is null!\n");
return NS_ERROR_FAILURE;
}
// get flavor list that includes all acceptable flavors (including ones obtained through
// conversion)
nsCOMPtr<nsISupportsArray> flavorList;
nsresult errCode = aTransferable->FlavorsTransferableCanImport ( getter_AddRefs(flavorList) );
if ( NS_FAILED(errCode) )
return NS_ERROR_FAILURE;
// Walk through flavors and see which flavor matches the one being pasted:
PRUint32 cnt;
flavorList->Count(&cnt);
nsCAutoString foundFlavor;
for ( PRUint32 i = 0; i < cnt; ++i ) {
nsCOMPtr<nsISupports> genericFlavor;
flavorList->GetElementAt ( i, getter_AddRefs(genericFlavor) );
nsCOMPtr<nsISupportsString> currentFlavor (do_QueryInterface(genericFlavor));
if ( currentFlavor ) {
nsXPIDLCString flavorStr;
currentFlavor->ToString(getter_Copies(flavorStr));
if (DoConvert(gdk_atom_intern(flavorStr, 1))) {
foundFlavor = flavorStr;
break;
}
}
}
#ifdef DEBUG_CLIPBOARD
printf(" Got the callback: '%s', %d\n",
mSelectionData.data, mSelectionData.length);
#endif /* DEBUG_CLIPBOARD */
// We're back from the callback, no longer blocking:
mBlocking = PR_FALSE;
//
// Now we have data in mSelectionData.data.
// We just have to copy it to the transferable.
//
#if 0
// pinkerton - we have the flavor already from above, so we don't need
// to re-derrive it.
nsString *name = new nsString((const char*)gdk_atom_name(mSelectionData.type));
int format = GetFormat(*name);
df->SetString((const char*)gdk_atom_name(sSelTypes[format]));
#endif
nsCOMPtr<nsISupports> genericDataWrapper;
nsPrimitiveHelpers::CreatePrimitiveForData ( foundFlavor, mSelectionData.data, mSelectionData.length, getter_AddRefs(genericDataWrapper) );
aTransferable->SetTransferData(foundFlavor,
genericDataWrapper,
mSelectionData.length);
//delete name;
// transferable is now copying the data, so we can free it.
// g_free(mSelectionData.data);
mSelectionData.data = nsnull;
mSelectionData.length = 0;
gtk_drag_source_unset(mWidget);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval)
{
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsDragService::GetCurrentSession (nsIDragSession **aSession)
{
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
void
nsDragService::DragLeave (GtkWidget *widget,
GdkDragContext *context,
guint time)
{
g_print("leave\n");
//gHaveDrag = PR_FALSE;
}
//-------------------------------------------------------------------------
PRBool
nsDragService::DragMotion(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
g_print("drag motion\n");
GtkWidget *source_widget;
#if 0
if (!gHaveDrag) {
gHaveDrag = PR_TRUE;
}
#endif
source_widget = gtk_drag_get_source_widget (context);
g_print("motion, source %s\n", source_widget ?
gtk_type_name (GTK_OBJECT (source_widget)->klass->type) :
"unknown");
gdk_drag_status (context, context->suggested_action, time);
return PR_TRUE;
}
//-------------------------------------------------------------------------
PRBool
nsDragService::DragDrop(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time)
{
g_print("drop\n");
//gHaveDrag = PR_FALSE;
if (context->targets){
gtk_drag_get_data (widget, context,
GPOINTER_TO_INT (context->targets->data),
time);
return PR_TRUE;
}
return PR_FALSE;
}
//-------------------------------------------------------------------------
void
nsDragService::DragDataReceived (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *data,
guint info,
guint time)
{
if ((data->length >= 0) && (data->format == 8)) {
g_print ("Received \"%s\"\n", (gchar *)data->data);
gtk_drag_finish (context, PR_TRUE, PR_FALSE, time);
return;
}
gtk_drag_finish (context, PR_FALSE, PR_FALSE, time);
}
//-------------------------------------------------------------------------
void
nsDragService::DragDataGet(GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
gtk_selection_data_set (selection_data,
selection_data->target,
8, (guchar *)"I'm Data!", 9);
}
//-------------------------------------------------------------------------
void
nsDragService::DragDataDelete(GtkWidget *widget,
GdkDragContext *context,
gpointer data)
{
g_print ("Delete the data!\n");
}

View File

@@ -0,0 +1,109 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsDragService_h__
#define nsDragService_h__
#include "nsBaseDragService.h"
#include <gtk/gtk.h>
/**
* Native GTK DragService wrapper
*/
class nsDragService : public nsBaseDragService
{
public:
nsDragService();
virtual ~nsDragService();
NS_DECL_ISUPPORTS_INHERITED
// nsIDragService
NS_IMETHOD InvokeDragSession (nsISupportsArray * anArrayTransferables,
nsIScriptableRegion * aRegion, PRUint32 aActionType);
NS_IMETHOD GetCurrentSession (nsIDragSession ** aSession);
// nsIDragSession
NS_IMETHOD GetData (nsITransferable * aTransferable, PRUint32 anItem);
NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems);
NS_IMETHOD IsDataFlavorSupported(const char *aDataFlavor, PRBool *_retval);
NS_IMETHOD StartDragSession();
NS_IMETHOD EndDragSession();
GtkTargetList *RegisterDragItemsAndFlavors(nsISupportsArray *inArray);
protected:
PRBool DoConvert(GdkAtom type);
static PRBool gHaveDrag;
static void DragLeave(GtkWidget *widget,
GdkDragContext *context,
guint time);
static PRBool DragMotion(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static PRBool DragDrop(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
guint time);
static void DragDataReceived(GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *data,
guint info,
guint time);
static void DragDataGet(GtkWidget *widget,
GdkDragContext *context,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data);
static void DragDataDelete(GtkWidget *widget,
GdkDragContext *context,
gpointer data);
private:
GdkDragAction mActionType;
PRUint32 mNumFlavors;
GtkWidget *mWidget;
GdkDragContext *mDragContext;
GtkSelectionData mSelectionData;
PRBool mBlocking;
};
#endif // nsDragService_h__

View File

@@ -0,0 +1,304 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsCOMPtr.h"
#include "nsIComponentManager.h"
#include "nsFilePicker.h"
NS_IMPL_ISUPPORTS1(nsFilePicker, nsIFilePicker)
//-------------------------------------------------------------------------
//
// nsFilePicker constructor
//
//-------------------------------------------------------------------------
nsFilePicker::nsFilePicker()
{
NS_INIT_REFCNT();
mWidget = nsnull;
mDisplayDirectory = nsnull;
mFilterMenu = nsnull;
mOptionMenu = nsnull;
mNumberOfFilters = 0;
}
//-------------------------------------------------------------------------
//
// nsFilePicker destructor
//
//-------------------------------------------------------------------------
nsFilePicker::~nsFilePicker()
{
if (mFilterMenu)
{
GtkWidget *menu_item;
GList *list = g_list_first(GTK_MENU_SHELL(mFilterMenu)->children);
for (;list; list = list->next)
{
menu_item = GTK_WIDGET(list->data);
gchar *data = (gchar*)gtk_object_get_data(GTK_OBJECT(menu_item), "filters");
if (data)
nsCRT::free(data);
}
}
gtk_widget_destroy(mWidget);
}
static void file_ok_clicked(GtkWidget *w, PRBool *ret)
{
g_print("user hit ok\n");
*ret = PR_TRUE;
gtk_main_quit();
}
static void file_cancel_clicked(GtkWidget *w, PRBool *ret)
{
g_print("user hit cancel\n");
*ret = PR_FALSE;
gtk_main_quit();
}
static void filter_item_activated(GtkWidget *w, gpointer data)
{
// nsFilePicker *f = (nsFilePicker*)data;
gchar *foo = (gchar*)gtk_object_get_data(GTK_OBJECT(w), "filters");
g_print("filter_item_activated(): %s\n", foo);
}
//-------------------------------------------------------------------------
//
// Show - Display the file dialog
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::Show(PRInt16 *retval)
{
NS_ENSURE_ARG_POINTER(retval);
PRBool ret;
if (mWidget) {
// make things shorter
GtkFileSelection *fs = GTK_FILE_SELECTION(mWidget);
if (mNumberOfFilters != 0)
{
gtk_option_menu_set_menu(GTK_OPTION_MENU(mOptionMenu), mFilterMenu);
}
else
gtk_widget_hide(mOptionMenu);
#if 0
if (mDisplayDirectory)
gtk_file_selection_complete(fs, "/");
#endif
// gtk_window_set_modal(GTK_WINDOW(mWidget), PR_TRUE);
gtk_widget_show(mWidget);
// handle close, destroy, etc on the dialog
gtk_signal_connect(GTK_OBJECT(fs->ok_button), "clicked",
GTK_SIGNAL_FUNC(file_ok_clicked),
&ret);
gtk_signal_connect(GTK_OBJECT(fs->cancel_button), "clicked",
GTK_SIGNAL_FUNC(file_cancel_clicked),
&ret);
// start new loop. ret is set in the above callbacks.
gtk_main();
}
else {
ret = PR_FALSE;
}
if (ret)
*retval = returnOK;
else
*retval = returnCancel;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the list of filters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::SetFilterList(PRInt32 aNumberOfFilters,
const PRUnichar **aTitles,
const PRUnichar **filters)
{
#if 0
GtkWidget *menu_item;
mNumberOfFilters = aNumberOfFilters;
mTitles = aTitles;
mFilters = aFilters;
mFilterMenu = gtk_menu_new();
for(unsigned int i=0; i < aNumberOfFilters; i++)
{
// we need *.{htm, html, xul, etc}
char *foo = aTitles[i].ToNewCString();
char *filters = aFilters[i].ToNewCString();
printf("%20s %s\n", foo, filters);
menu_item = gtk_menu_item_new_with_label(nsAutoCString(aTitles[i]));
gtk_object_set_data(GTK_OBJECT(menu_item), "filters", filters);
gtk_signal_connect(GTK_OBJECT(menu_item),
"activate",
GTK_SIGNAL_FUNC(filter_item_activated),
this);
gtk_menu_append(GTK_MENU(mFilterMenu), menu_item);
gtk_widget_show(menu_item);
nsCRT::free(foo);
}
#endif
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::GetFile(nsIFileSpec **aFile)
{
NS_ENSURE_ARG_POINTER(*aFile);
if (mWidget) {
gchar *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mWidget));
nsCOMPtr<nsIFileSpec> fileSpec(do_CreateInstance("component://netscape/filespec"));
NS_ENSURE_TRUE(fileSpec, NS_ERROR_FAILURE);
fileSpec->SetNativePath(fn);
*aFile = fileSpec;
NS_ADDREF(*aFile);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetSelectedFilter(PRInt32 *aType)
{
NS_ENSURE_ARG_POINTER(aType);
*aType = mSelectedType;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the file + path
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::SetDefaultString(const PRUnichar *aString)
{
if (mWidget) {
gtk_file_selection_set_filename(GTK_FILE_SELECTION(mWidget),
(const gchar*)nsAutoCString(aString));
}
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::GetDefaultString(PRUnichar **aString)
{
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
//
// Set the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::SetDisplayDirectory(nsIFileSpec *aDirectory)
{
mDisplayDirectory = aDirectory;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::GetDisplayDirectory(nsIFileSpec **aDirectory)
{
*aDirectory = mDisplayDirectory;
NS_IF_ADDREF(*aDirectory);
return NS_OK;
}
NS_IMETHODIMP nsFilePicker::Create(nsIDOMWindow *aParent,
const PRUnichar *aTitle,
PRInt16 aMode)
{
return nsBaseFilePicker::Create(aParent, aTitle, aMode);
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFilePicker::CreateNative(nsIWidget *aParent,
const PRUnichar *aTitle,
PRInt16 aMode)
{
mWidget = gtk_file_selection_new((const gchar *)nsAutoCString(aTitle));
gtk_signal_connect(GTK_OBJECT(mWidget),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
gtk_button_box_set_layout(GTK_BUTTON_BOX(GTK_FILE_SELECTION(mWidget)->button_area), GTK_BUTTONBOX_SPREAD);
mOptionMenu = gtk_option_menu_new();
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(mWidget)->main_vbox), mOptionMenu, PR_FALSE, PR_FALSE, 0);
gtk_widget_show(mOptionMenu);
// Hide the file column for the folder case.
if (aMode == nsIFilePicker::modeGetFolder) {
gtk_widget_hide((GTK_FILE_SELECTION(mWidget)->file_list)->parent);
}
return NS_OK;
}
gint
nsFilePicker::DestroySignal(GtkWidget * aGtkWidget,
nsFilePicker* aWidget)
{
aWidget->OnDestroySignal(aGtkWidget);
return TRUE;
}
void
nsFilePicker::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mWidget) {
mWidget = nsnull;
}
}

View File

@@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the Mozilla browser.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef nsFilePicker_h__
#define nsFilePicker_h__
#include "nsBaseFilePicker.h"
#include <gtk/gtk.h>
/**
* Native GTK FileSelector wrapper
*/
class nsFilePicker : public nsBaseFilePicker
{
public:
nsFilePicker();
virtual ~nsFilePicker();
NS_DECL_ISUPPORTS
NS_DECL_NSIFILEPICKER
protected:
/* method from nsBaseFilePicker */
NS_IMETHOD CreateNative(nsIWidget *aParent,
const PRUnichar *aTitle,
PRInt16 aMode);
static gint DestroySignal(GtkWidget * aGtkWidget,
nsFilePicker* aWidget);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
GtkWidget *mWidget;
GtkWidget *mOptionMenu;
GtkWidget *mFilterMenu;
PRUint32 mNumberOfFilters;
const nsString* mTitles;
const nsString* mFilters;
nsString mDefault;
nsIFileSpec *mDisplayDirectory;
PRInt16 mSelectedType;
};
#endif // nsFilePicker_h__

View File

@@ -0,0 +1,322 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsFileWidget.h"
#include "nsIToolkit.h"
NS_IMPL_ISUPPORTS1(nsFileWidget, nsIFileWidget)
//-------------------------------------------------------------------------
//
// nsFileWidget constructor
//
//-------------------------------------------------------------------------
nsFileWidget::nsFileWidget() : nsIFileWidget()
{
NS_INIT_REFCNT();
mWidget = nsnull;
mDisplayDirectory = nsnull;
mFilterMenu = nsnull;
mOptionMenu = nsnull;
mNumberOfFilters = 0;
}
//-------------------------------------------------------------------------
//
// nsFileWidget destructor
//
//-------------------------------------------------------------------------
nsFileWidget::~nsFileWidget()
{
if (mFilterMenu)
{
GtkWidget *menu_item;
GList *list = g_list_first(GTK_MENU_SHELL(mFilterMenu)->children);
for (;list; list = list->next)
{
menu_item = GTK_WIDGET(list->data);
gchar *data = (gchar*)gtk_object_get_data(GTK_OBJECT(menu_item), "filters");
if (data)
nsCRT::free(data);
}
}
gtk_widget_destroy(mWidget);
}
static void file_ok_clicked(GtkWidget *w, PRBool *ret)
{
g_print("user hit ok\n");
*ret = PR_TRUE;
gtk_main_quit();
}
static void file_cancel_clicked(GtkWidget *w, PRBool *ret)
{
g_print("user hit cancel\n");
*ret = PR_FALSE;
gtk_main_quit();
}
static void filter_item_activated(GtkWidget *w, gpointer data)
{
// nsFileWidget *f = (nsFileWidget*)data;
gchar *foo = (gchar*)gtk_object_get_data(GTK_OBJECT(w), "filters");
g_print("filter_item_activated(): %s\n", foo);
}
//-------------------------------------------------------------------------
//
// Show - Display the file dialog
//
//-------------------------------------------------------------------------
PRBool nsFileWidget::Show()
{
PRBool ret;
if (mWidget) {
// make things shorter
GtkFileSelection *fs = GTK_FILE_SELECTION(mWidget);
if (mNumberOfFilters != 0)
{
gtk_option_menu_set_menu(GTK_OPTION_MENU(mOptionMenu), mFilterMenu);
}
else
gtk_widget_hide(mOptionMenu);
#if 0
if (mDisplayDirectory)
gtk_file_selection_complete(fs, "/");
#endif
// gtk_window_set_modal(GTK_WINDOW(mWidget), PR_TRUE);
gtk_widget_show(mWidget);
// handle close, destroy, etc on the dialog
gtk_signal_connect(GTK_OBJECT(fs->ok_button), "clicked",
GTK_SIGNAL_FUNC(file_ok_clicked),
&ret);
gtk_signal_connect(GTK_OBJECT(fs->cancel_button), "clicked",
GTK_SIGNAL_FUNC(file_cancel_clicked),
&ret);
// start new loop. ret is set in the above callbacks.
gtk_main();
}
else {
ret = PR_FALSE;
}
return ret;
}
//-------------------------------------------------------------------------
//
// Set the list of filters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::SetFilterList(PRUint32 aNumberOfFilters,
const nsString aTitles[],
const nsString aFilters[])
{
GtkWidget *menu_item;
mNumberOfFilters = aNumberOfFilters;
mTitles = aTitles;
mFilters = aFilters;
mFilterMenu = gtk_menu_new();
for(unsigned int i=0; i < aNumberOfFilters; i++)
{
// we need *.{htm, html, xul, etc}
char *foo = aTitles[i].ToNewCString();
char *filters = aFilters[i].ToNewCString();
printf("%20s %s\n", foo, filters);
menu_item = gtk_menu_item_new_with_label(nsAutoCString(aTitles[i]));
gtk_object_set_data(GTK_OBJECT(menu_item), "filters", filters);
gtk_signal_connect(GTK_OBJECT(menu_item),
"activate",
GTK_SIGNAL_FUNC(filter_item_activated),
this);
gtk_menu_append(GTK_MENU(mFilterMenu), menu_item);
gtk_widget_show(menu_item);
nsCRT::free(foo);
}
return NS_OK;
}
NS_IMETHODIMP nsFileWidget::GetFile(nsFileSpec& aFile)
{
if (mWidget) {
gchar *fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION(mWidget));
aFile = fn; // Put the filename into the nsFileSpec instance.
}
return NS_OK;
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::GetSelectedType(PRInt16& theType)
{
theType = mSelectedType;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the file + path
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::SetDefaultString(const nsString& aString)
{
if (mWidget) {
gtk_file_selection_set_filename(GTK_FILE_SELECTION(mWidget),
(const gchar*)nsAutoCString(aString));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::SetDisplayDirectory(const nsFileSpec& aDirectory)
{
mDisplayDirectory = aDirectory;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the display directory
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::GetDisplayDirectory(nsFileSpec& aDirectory)
{
aDirectory = mDisplayDirectory;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsFileWidget::Create(nsIWidget *aParent,
const nsString& aTitle,
nsFileDlgMode aMode,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell,
nsIToolkit *aToolkit,
void *aInitData)
{
mMode = aMode;
mTitle.SetLength(0);
mTitle.Append(aTitle);
mWidget = gtk_file_selection_new((const gchar *)nsAutoCString(aTitle));
gtk_signal_connect(GTK_OBJECT(mWidget),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
gtk_button_box_set_layout(GTK_BUTTON_BOX(GTK_FILE_SELECTION(mWidget)->button_area), GTK_BUTTONBOX_SPREAD);
mOptionMenu = gtk_option_menu_new();
gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(mWidget)->main_vbox), mOptionMenu, PR_FALSE, PR_FALSE, 0);
gtk_widget_show(mOptionMenu);
// Hide the file column for the folder case.
if (aMode == eMode_getfolder) {
gtk_widget_hide((GTK_FILE_SELECTION(mWidget)->file_list)->parent);
}
return NS_OK;
}
gint
nsFileWidget::DestroySignal(GtkWidget * aGtkWidget,
nsFileWidget* aWidget)
{
aWidget->OnDestroySignal(aGtkWidget);
return TRUE;
}
void
nsFileWidget::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mWidget) {
mWidget = nsnull;
}
}
nsFileDlgResults nsFileWidget::GetFile(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec)
{
Create(aParent, promptString, eMode_load, nsnull, nsnull);
if (Show() == PR_TRUE)
{
GetFile(theFileSpec);
return nsFileDlgResults_OK;
}
return nsFileDlgResults_Cancel;
}
nsFileDlgResults nsFileWidget::GetFolder(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec)
{
Create(aParent, promptString, eMode_getfolder, nsnull, nsnull);
if (Show() == PR_TRUE)
{
GetFile(theFileSpec);
return nsFileDlgResults_OK;
}
return nsFileDlgResults_Cancel;
}
nsFileDlgResults nsFileWidget::PutFile(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec)
{
Create(aParent, promptString, eMode_save, nsnull, nsnull);
if (Show() == PR_TRUE)
{
GetFile(theFileSpec);
return nsFileDlgResults_OK;
}
return nsFileDlgResults_Cancel;
}

View File

@@ -0,0 +1,102 @@
/* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsFileWidget_h__
#define nsFileWidget_h__
#include "nsIWidget.h"
#include "nsIFileWidget.h"
#include <gtk/gtk.h>
class nsIToolkit;
/**
* Native GTK FileSelector wrapper
*/
class nsFileWidget : public nsIFileWidget
{
public:
nsFileWidget();
virtual ~nsFileWidget();
NS_DECL_ISUPPORTS
// nsIWidget interface
NS_IMETHOD Create(nsIWidget *aParent,
const nsString& aTitle,
nsFileDlgMode aMode,
nsIDeviceContext *aContext = nsnull,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
void *aInitData = nsnull);
// nsIFileWidget part
virtual PRBool Show();
NS_IMETHOD GetFile(nsFileSpec& aFile);
NS_IMETHOD SetDefaultString(const nsString& aFile);
NS_IMETHOD SetFilterList(PRUint32 aNumberOfFilters,
const nsString aTitles[],
const nsString aFilters[]);
NS_IMETHOD GetDisplayDirectory(nsFileSpec& aDirectory);
NS_IMETHOD SetDisplayDirectory(const nsFileSpec& aDirectory);
virtual nsFileDlgResults GetFile(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec);
virtual nsFileDlgResults GetFolder(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec);
virtual nsFileDlgResults PutFile(nsIWidget *aParent,
const nsString &promptString,
nsFileSpec &theFileSpec);
NS_IMETHOD GetSelectedType(PRInt16& theType);
protected:
static gint DestroySignal(GtkWidget * aGtkWidget,
nsFileWidget* aWidget);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
GtkWidget *mWidget;
nsString mTitle;
GtkWidget *mOptionMenu;
GtkWidget *mFilterMenu;
nsFileDlgMode mMode;
PRUint32 mNumberOfFilters;
const nsString* mTitles;
const nsString* mFilters;
nsString mDefault;
nsFileSpec mDisplayDirectory;
PRInt16 mSelectedType;
};
#endif // nsFileWidget_h__

View File

@@ -0,0 +1,395 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsFontRetrieverService.h"
#include "nsIWidget.h"
#include <ctype.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include "X11/Xlib.h"
#include "X11/Xutil.h"
#include "nsFont.h"
#include "nsVoidArray.h"
#include "nsFontSizeIterator.h"
NS_IMPL_ISUPPORTS2(nsFontRetrieverService, nsIFontRetrieverService, nsIFontNameIterator)
//----------------------------------------------------------
nsFontRetrieverService::nsFontRetrieverService()
{
NS_INIT_REFCNT();
mFontList = nsnull;
mSizeIter = nsnull;
mNameIterInx = 0;
}
//----------------------------------------------------------
nsFontRetrieverService::~nsFontRetrieverService()
{
if (nsnull != mFontList) {
for (PRInt32 i=0;i<mFontList->Count();i++) {
FontInfo * font = (FontInfo *)mFontList->ElementAt(i);
if (font->mSizes) {
delete font->mSizes;
}
delete font;
}
delete mFontList;
}
NS_IF_RELEASE(mSizeIter);
}
//----------------------------------------------------------
//-- nsIFontRetrieverService
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::CreateFontNameIterator( nsIFontNameIterator** aIterator )
{
if (nsnull == aIterator) {
return NS_ERROR_FAILURE;
}
if (nsnull == mFontList) {
LoadFontList();
}
*aIterator = this;
NS_ADDREF_THIS();
return NS_OK;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::CreateFontSizeIterator( const nsString & aFontName,
nsIFontSizeIterator** aIterator )
{
// save value in case someone externally is using it
PRInt32 saveIterInx = mNameIterInx;
PRBool found = PR_FALSE;
Reset();
do {
nsAutoString name;
Get(&name);
if (name.Equals(aFontName)) {
found = PR_TRUE;
break;
}
} while (Advance() == NS_OK);
if (found) {
if (nsnull == mSizeIter) {
mSizeIter = new nsFontSizeIterator();
}
NS_ASSERTION( nsnull != mSizeIter, "nsFontSizeIterator instance pointer is null");
*aIterator = (nsIFontSizeIterator *)mSizeIter;
NS_ADDREF(mSizeIter);
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
mSizeIter->SetFontInfo(fontInfo);
mNameIterInx = saveIterInx;
return NS_OK;
}
mNameIterInx = saveIterInx;
return NS_ERROR_FAILURE;
}
//----------------------------------------------------------
//-- nsIFontNameIterator
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::Reset()
{
mNameIterInx = 0;
return NS_OK;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::Get( nsString* aFontName )
{
if (mNameIterInx < mFontList->Count()) {
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
*aFontName = fontInfo->mName;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::Advance()
{
if (mNameIterInx < mFontList->Count()-1) {
mNameIterInx++;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
//------------------------------
static FontInfo * GetFontInfo(nsVoidArray * aFontList, char * aName)
{
nsAutoString name(aName);
PRInt32 i;
PRInt32 cnt = aFontList->Count();
for (i=0;i<cnt;i++) {
FontInfo * fontInfo = (FontInfo *)aFontList->ElementAt(i);
if (fontInfo->mName.Equals(name)) {
return fontInfo;
}
}
FontInfo * fontInfo = new FontInfo();
fontInfo->mName = aName;
//printf("Adding [%s]\n", aName);fflush(stdout);
fontInfo->mIsScalable = PR_FALSE; // X fonts aren't scalable right??
fontInfo->mSizes = nsnull;
aFontList->AppendElement(fontInfo);
return fontInfo;
}
//------------------------------
static void AddSizeToFontInfo(FontInfo * aFontInfo, PRInt32 aSize)
{
nsVoidArray * sizes;
if (nsnull == aFontInfo->mSizes) {
sizes = new nsVoidArray();
aFontInfo->mSizes = sizes;
} else {
sizes = aFontInfo->mSizes;
}
PRInt32 i;
PRInt32 cnt = sizes->Count();
for (i=0;i<cnt;i++) {
PRInt32 size = (int)sizes->ElementAt(i);
if (size == aSize) {
return;
}
}
sizes->AppendElement((void *)aSize);
}
//---------------------------------------------------
// XXX - Hack - Parts of this will need to be reworked
//
// This method does brute force parcing for 4 different formats:
//
// 1) The format -*-*-*-*-*-* etc.
// -misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-8
//
// 2) Name-size format
// lucidasans-10
//
// 3) Name-style-size
// lucidasans-bold-10
//
// 4) Name only (implicit size)
// 6x13
//
//--------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::LoadFontList()
{
char * pattern = "*";
int nnames = 1024;
int available = nnames+1;
int i;
char **fonts;
XFontStruct *info;
if (nsnull == mFontList) {
mFontList = new nsVoidArray();
if (nsnull == mFontList) {
return NS_ERROR_FAILURE;
}
}
/* Get list of fonts matching pattern */
for (;;) {
// the following line is VERY slow to return
fonts = XListFontsWithInfo(GDK_DISPLAY(), pattern, nnames,
&available, &info);
if (fonts == NULL || available < nnames)
break;
XFreeFontInfo(fonts, info, available);
nnames = available * 2;
}
if (fonts == NULL) {
fprintf(stderr, "pattern \"%s\" unmatched\n", pattern);
return NS_ERROR_FAILURE;
}
#if 0 // debug
// print out all the retrieved fonts
printf("-----------------------------\n");
for (i=0; i<available; i++) {
printf("[%s]i\n", fonts[i]);
}
printf("-----------------------------\n");
#endif
// this code assumes all like fonts are grouped together
// currentName is the current name of the font we are gathering
// sizes for, when the name changes we create a new FontInfo object
// but it also takes into account fonts of similar names when it
// goes to add then and disregards duplicates
char buffer[1024];
char currentName[1024];
FontInfo * font = nsnull;
currentName[0] = 0;
for (i=0; i<available; i++) {
// This is kind of lame, but it will have to do for now
strcpy(buffer, fonts[i]);
// Start by checking to see if the name begins with a dash
char * ptr = buffer;
if (buffer[0] == '-') { //Format #1
PRInt32 cnt = 0;
// skip first two '-'
do {
if (*ptr == '-') cnt++;
ptr++;
} while (cnt < 2);
// find the dash at the end of the name
char * end = strchr(ptr, '-');
if (end) {
*end = 0;
// Check to see if we need to create a new FontInfo obj
// and set the currentName var to this guys font name
if (strcmp(currentName, ptr) || NULL == font) {
font = GetFontInfo(mFontList, ptr);
strcpy(currentName, ptr);
}
if (nsnull == font->mSizes) {
font->mSizes = new nsVoidArray();
}
ptr = end+1; // skip past the dash that was set to zero
cnt = 0;
// now skip ahead 4 dashes
do {
if (*ptr == '-') cnt++;
ptr++;
} while (cnt < 4);
// find the dash after the size
end = strchr(ptr, '-');
if (end) {
*end = 0;
PRInt32 size;
sscanf(ptr, "%d", &size);
AddSizeToFontInfo(font, size);
}
}
} else { // formats 2,3,4
// no leading dash means the start of the
// buffer is the start of the name
// this checks for a dash at the end of the font name
// which means there is a size at the end
char * end = strchr(buffer, '-');
if (end) { // Format 2,3
*end = 0;
// Check to see if we need to create a new FontInfo obj
// and set the currentName var to this guys font name
if (strcmp(currentName, buffer) || NULL == font) {
font = GetFontInfo(mFontList, buffer);
strcpy(currentName, buffer);
}
end++; // advance past the dash
// check to see if we have a number
ptr = end;
if (isalpha(*ptr)) { // Format 3
// skip until next dash
end = strchr(ptr, '-');
if (end) {
*end = 0;
ptr = end+1;
}
}
PRInt32 size;
// yes, it has a dash at the end so it must have the size
// check to see if the size is terminated by a dash
// it shouldn't be
char * end2 = strchr(ptr, '-');
if (end2) *end2 = 0; // put terminator at the dash
sscanf(end, "%d", &size);
AddSizeToFontInfo(font, size);
} else { // Format #4
// The font has an implicit size,
// so there is nothing to parse for size
// so we can't really do much here
// Check to see if we need to create a new FontInfo obj
// and set the currentName var to this guys font name
if (strcmp(currentName, buffer) || NULL == font) {
font = GetFontInfo(mFontList, buffer);
strcpy(currentName, buffer);
}
}
}
}
XFreeFontInfo(fonts, info, available);
return NS_OK;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontRetrieverService::IsFontScalable(const nsString & aFontName,
PRBool* aResult )
{
// save value in case someone externally is using it
PRInt32 saveIterInx = mNameIterInx;
PRBool found = PR_FALSE;
Reset();
do {
nsAutoString name;
Get(&name);
if (name.Equals(aFontName)) {
found = PR_TRUE;
break;
}
} while (Advance() == NS_OK);
if (found) {
FontInfo * fontInfo = (FontInfo *)mFontList->ElementAt(mNameIterInx);
*aResult = fontInfo->mIsScalable;
mNameIterInx = saveIterInx;
return NS_OK;
}
mNameIterInx = saveIterInx;
return NS_ERROR_FAILURE;
}

View File

@@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsFontRetrieverService
#define __nsFontRetrieverService
#include "nsIFontRetrieverService.h"
#include "nsIFontNameIterator.h"
class nsVoidArray;
class nsFontSizeIterator;
class nsFontRetrieverService: public nsIFontRetrieverService,
public nsIFontNameIterator
{
public:
nsFontRetrieverService();
virtual ~nsFontRetrieverService();
NS_DECL_ISUPPORTS
// nsIFontRetrieverService
NS_IMETHOD CreateFontNameIterator( nsIFontNameIterator** aIterator );
NS_IMETHOD CreateFontSizeIterator( const nsString & aFontName, nsIFontSizeIterator** aIterator );
NS_IMETHOD IsFontScalable( const nsString & aFontName, PRBool* aResult );
// nsIFontNameIterator
NS_IMETHOD Reset();
NS_IMETHOD Get( nsString* aFontName );
NS_IMETHOD Advance();
protected:
NS_IMETHOD LoadFontList();
nsVoidArray * mFontList;
PRInt32 mNameIterInx;
nsFontSizeIterator * mSizeIter;
};
#endif

View File

@@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsFontSizeIterator.h"
#include "nsFont.h"
#include "nsVoidArray.h"
NS_IMPL_ADDREF(nsFontSizeIterator)
NS_IMPL_RELEASE(nsFontSizeIterator)
NS_IMPL_QUERY_INTERFACE(nsFontSizeIterator, nsIFontSizeIterator::GetIID())
//----------------------------------------------------------
nsFontSizeIterator::nsFontSizeIterator()
{
NS_INIT_REFCNT();
mFontInfo = nsnull;
mSizeIterInx = 0;
}
//----------------------------------------------------------
nsFontSizeIterator::~nsFontSizeIterator()
{
}
///----------------------------------------------------------
//-- nsIFontNameIterator
//----------------------------------------------------------
NS_IMETHODIMP nsFontSizeIterator::Reset()
{
mSizeIterInx = 0;
return NS_OK;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontSizeIterator::Get( double* aFontSize )
{
if (nsnull != mFontInfo->mSizes &&
mFontInfo->mSizes->Count() > 0 &&
mSizeIterInx < mFontInfo->mSizes->Count()) {
PRUint32 size = (PRUint32)mFontInfo->mSizes->ElementAt(mSizeIterInx);
*aFontSize = (double)size;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontSizeIterator::Advance()
{
if (nsnull != mFontInfo->mSizes &&
mFontInfo->mSizes->Count() > 0 &&
mSizeIterInx < mFontInfo->mSizes->Count()-2) {
mSizeIterInx++;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
//----------------------------------------------------------
NS_IMETHODIMP nsFontSizeIterator::SetFontInfo( FontInfo * aFontInfo )
{
mFontInfo = aFontInfo;
return NS_OK;
}

View File

@@ -0,0 +1,59 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsFontSizeIterator
#define __nsFontSizeIterator
#include "nsIFontSizeIterator.h"
#include "nsString.h"
class nsVoidArray;
typedef struct {
nsString mName;
PRBool mIsScalable;
nsVoidArray * mSizes;
} FontInfo;
class nsFontSizeIterator: public nsIFontSizeIterator {
public:
nsFontSizeIterator();
virtual ~nsFontSizeIterator();
NS_DECL_ISUPPORTS
// nsIFontSizeIterator
NS_IMETHOD Reset();
NS_IMETHOD Get( double* aFontSize );
NS_IMETHOD Advance();
// Native impl
NS_IMETHOD SetFontInfo( FontInfo * aFontInfo );
protected:
FontInfo * mFontInfo;
PRInt32 mSizeIterInx; // current index of iter
};
#endif

View File

@@ -0,0 +1,967 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsWidget.h"
#include "nsWindow.h"
#include "nsScrollbar.h"
#include "nsIFileWidget.h"
#include "nsGUIEvent.h"
#include "nsIMenu.h"
#include "nsIMenuItem.h"
#include "nsIMenuListener.h"
#include "nsTextWidget.h"
#include "nsICharsetConverterManager.h"
#include "nsIPlatformCharset.h"
#include "nsIServiceManager.h"
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
#include "stdio.h"
#include "ctype.h"
#include "gtk/gtk.h"
#include "nsGtkEventHandler.h"
#include <gdk/gdkkeysyms.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#ifdef DEBUG_pavlov
//#define DEBUG_EVENTS 1
#endif
struct EventInfo {
nsWidget *widget; // the widget
nsRect *rect; // the rect
};
//==============================================================
void InitAllocationEvent(GtkAllocation *aAlloc,
gpointer p,
nsSizeEvent &anEvent,
PRUint32 aEventType)
{
anEvent.message = aEventType;
anEvent.widget = (nsWidget *) p;
anEvent.eventStructType = NS_SIZE_EVENT;
if (aAlloc != nsnull) {
// HACK
// nsRect *foo = new nsRect(aAlloc->x, aAlloc->y, aAlloc->width, aAlloc->height);
nsRect *foo = new nsRect(0, 0, aAlloc->width, aAlloc->height);
anEvent.windowSize = foo;
// anEvent.point.x = aAlloc->x;
// anEvent.point.y = aAlloc->y;
// HACK
anEvent.point.x = 0;
anEvent.point.y = 0;
anEvent.mWinWidth = aAlloc->width;
anEvent.mWinHeight = aAlloc->height;
}
anEvent.time = PR_IntervalNow();
}
//==============================================================
void InitConfigureEvent(GdkEventConfigure *aConf,
gpointer p,
nsSizeEvent &anEvent,
PRUint32 aEventType)
{
anEvent.message = aEventType;
anEvent.widget = (nsWidget *) p;
anEvent.eventStructType = NS_SIZE_EVENT;
if (aConf != nsnull) {
/* do we accually need to alloc a new rect, or can we just set the
current one */
nsRect *foo = new nsRect(aConf->x, aConf->y, aConf->width, aConf->height);
anEvent.windowSize = foo;
anEvent.point.x = aConf->x;
anEvent.point.y = aConf->y;
anEvent.mWinWidth = aConf->width;
anEvent.mWinHeight = aConf->height;
}
// this usually returns 0
anEvent.time = 0;
}
//==============================================================
void InitExposeEvent(GdkEventExpose *aGEE,
gpointer p,
nsPaintEvent &anEvent,
PRUint32 aEventType)
{
anEvent.message = aEventType;
anEvent.widget = (nsWidget *) p;
anEvent.eventStructType = NS_PAINT_EVENT;
if (aGEE != nsnull)
{
#ifdef DEBUG_EVENTS
g_print("expose event: x = %i , y = %i , w = %i , h = %i\n",
aGEE->area.x, aGEE->area.y,
aGEE->area.width, aGEE->area.height);
#endif
anEvent.point.x = aGEE->area.x;
anEvent.point.y = aGEE->area.y;
nsRect *rect = new nsRect(aGEE->area.x, aGEE->area.y,
aGEE->area.width, aGEE->area.height);
anEvent.rect = rect;
anEvent.time = gdk_event_get_time((GdkEvent*)aGEE);
}
}
//=============================================================
void UninitExposeEvent(GdkEventExpose *aGEE,
gpointer p,
nsPaintEvent &anEvent,
PRUint32 aEventType)
{
if (aGEE != nsnull) {
delete anEvent.rect;
}
}
struct nsKeyConverter {
int vkCode; // Platform independent key code
int keysym; // GDK keysym key code
};
//
// Netscape keycodes are defined in widget/public/nsGUIEvent.h
// GTK keycodes are defined in <gdk/gdkkeysyms.h>
//
struct nsKeyConverter nsKeycodes[] = {
{ NS_VK_CANCEL, GDK_Cancel },
{ NS_VK_BACK, GDK_BackSpace },
{ NS_VK_TAB, GDK_Tab },
{ NS_VK_TAB, GDK_ISO_Left_Tab },
{ NS_VK_CLEAR, GDK_Clear },
{ NS_VK_RETURN, GDK_Return },
{ NS_VK_SHIFT, GDK_Shift_L },
{ NS_VK_SHIFT, GDK_Shift_R },
{ NS_VK_CONTROL, GDK_Control_L },
{ NS_VK_CONTROL, GDK_Control_R },
{ NS_VK_ALT, GDK_Alt_L },
{ NS_VK_ALT, GDK_Alt_R },
{ NS_VK_PAUSE, GDK_Pause },
{ NS_VK_CAPS_LOCK, GDK_Caps_Lock },
{ NS_VK_ESCAPE, GDK_Escape },
{ NS_VK_SPACE, GDK_space },
{ NS_VK_PAGE_UP, GDK_Page_Up },
{ NS_VK_PAGE_DOWN, GDK_Page_Down },
{ NS_VK_END, GDK_End },
{ NS_VK_HOME, GDK_Home },
{ NS_VK_LEFT, GDK_Left },
{ NS_VK_UP, GDK_Up },
{ NS_VK_RIGHT, GDK_Right },
{ NS_VK_DOWN, GDK_Down },
{ NS_VK_PRINTSCREEN, GDK_Print },
{ NS_VK_INSERT, GDK_Insert },
{ NS_VK_DELETE, GDK_Delete },
{ NS_VK_MULTIPLY, GDK_KP_Multiply },
{ NS_VK_ADD, GDK_KP_Add },
{ NS_VK_SEPARATOR, GDK_KP_Separator },
{ NS_VK_SUBTRACT, GDK_KP_Subtract },
{ NS_VK_DECIMAL, GDK_KP_Decimal },
{ NS_VK_DIVIDE, GDK_KP_Divide },
{ NS_VK_RETURN, GDK_KP_Enter },
// NS doesn't have dash or equals distinct from the numeric keypad ones,
// so we'll use those for now. See bug 17008:
{ NS_VK_SUBTRACT, GDK_minus },
{ NS_VK_EQUALS, GDK_equal },
// and we don't have a single-quote symbol either:
{ NS_VK_QUOTE, GDK_apostrophe },
{ NS_VK_COMMA, GDK_comma },
{ NS_VK_PERIOD, GDK_period },
{ NS_VK_SLASH, GDK_slash },
{ NS_VK_BACK_SLASH, GDK_backslash },
{ NS_VK_BACK_QUOTE, GDK_grave },
{ NS_VK_OPEN_BRACKET, GDK_bracketleft },
{ NS_VK_CLOSE_BRACKET, GDK_bracketright },
{ NS_VK_QUOTE, GDK_quotedbl },
// Some shifted keys, see bug 15463.
// These should be subject to different keyboard mappings;
// how do we do that in gtk?
{ NS_VK_SEMICOLON, GDK_colon },
{ NS_VK_BACK_QUOTE, GDK_asciitilde },
{ NS_VK_COMMA, GDK_less },
{ NS_VK_PERIOD, GDK_greater },
{ NS_VK_SLASH, GDK_question },
{ NS_VK_1, GDK_exclam },
{ NS_VK_2, GDK_at },
{ NS_VK_3, GDK_numbersign },
{ NS_VK_4, GDK_dollar },
{ NS_VK_5, GDK_percent },
{ NS_VK_6, GDK_asciicircum },
{ NS_VK_7, GDK_ampersand },
{ NS_VK_8, GDK_asterisk },
{ NS_VK_9, GDK_parenleft },
{ NS_VK_0, GDK_parenright },
{ NS_VK_SUBTRACT, GDK_underscore },
{ NS_VK_EQUALS, GDK_plus }
};
void nsGtkWidget_InitNSKeyEvent(int aEventType, nsKeyEvent& aKeyEvent,
GtkWidget *w, gpointer p, GdkEventKey * event);
//==============================================================
// Input keysym is in gtk format; output is in NS_VK format
int nsPlatformToDOMKeyCode(GdkEventKey *aGEK)
{
int i;
int length = sizeof(nsKeycodes) / sizeof(struct nsKeyConverter);
int keysym = aGEK->keyval;
// First, try to handle alphanumeric input, not listed in nsKeycodes:
// most likely, more letters will be getting typed in than things in
// the key list, so we will look through these first.
// since X has different key symbols for upper and lowercase letters and
// mozilla does not, convert gdk's to mozilla's
if (keysym >= GDK_a && keysym <= GDK_z)
return keysym - GDK_a + NS_VK_A;
if (keysym >= GDK_A && keysym <= GDK_Z)
return keysym - GDK_A + NS_VK_A;
// numbers
if (keysym >= GDK_0 && keysym <= GDK_9)
return keysym - GDK_0 + NS_VK_0;
// keypad numbers
if (keysym >= GDK_KP_0 && keysym <= GDK_KP_9)
return keysym - GDK_KP_0 + NS_VK_NUMPAD0;
// misc other things
for (i = 0; i < length; i++) {
if (nsKeycodes[i].keysym == keysym)
return(nsKeycodes[i].vkCode);
}
// function keys
if (keysym >= GDK_F1 && keysym <= GDK_F24)
return keysym - GDK_F1 + NS_VK_F1;
#if defined(DEBUG_akkana) || defined(DEBUG_ftang)
printf("No match in nsPlatformToDOMKeyCode: keysym is 0x%x, string is %s\n", keysym, aGEK->string);
#endif
return((int)0);
}
//==============================================================
PRUint32 nsConvertCharCodeToUnicode(GdkEventKey* aGEK)
{
// For control chars, GDK sets string to be the actual ascii value.
// Map that to what nsKeyEvent wants, which currently --
// TEMPORARILY (the spec has changed and will be switched over
// when the tree opens for M11) --
// is the ascii for the actual event (e.g. 1 for control-a).
// This is only true for control chars; for alt chars, send the
// ascii for the key, i.e. a for alt-a.
if (aGEK->state & GDK_CONTROL_MASK)
{
if (aGEK->state & GDK_SHIFT_MASK)
return aGEK->string[0] + 'A' - 1;
else
return aGEK->string[0] + 'a' - 1;
}
// For now (obviously this will need to change for IME),
// only set a char code if the result is printable:
if (!isprint(aGEK->string[0]))
return 0;
// ALT keys in gdk give the upper case character in string,
// but we want the lower case char in char code
// unless shift was also pressed.
if (((aGEK->state & GDK_MOD1_MASK))
&& !(aGEK->state & GDK_SHIFT_MASK)
&& isupper(aGEK->string[0]))
return tolower(aGEK->string[0]);
//
// placeholder for something a little more interesting and correct
//
return aGEK->string[0];
}
//==============================================================
void InitKeyEvent(GdkEventKey *aGEK,
gpointer p,
nsKeyEvent &anEvent,
PRUint32 aEventType)
{
anEvent.message = aEventType;
anEvent.widget = (nsWidget *) p;
anEvent.eventStructType = NS_KEY_EVENT;
if (aGEK != nsnull) {
anEvent.keyCode = nsPlatformToDOMKeyCode(aGEK);
anEvent.charCode = 0;
anEvent.time = aGEK->time;
anEvent.isShift = (aGEK->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
anEvent.isControl = (aGEK->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
anEvent.isAlt = (aGEK->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
// XXX
anEvent.isMeta = PR_FALSE; //(aGEK->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
anEvent.point.x = 0;
anEvent.point.y = 0;
}
}
void InitKeyPressEvent(GdkEventKey *aGEK,
gpointer p,
nsKeyEvent &anEvent)
{
//
// init the basic event fields
//
anEvent.eventStructType = NS_KEY_EVENT;
anEvent.message = NS_KEY_PRESS;
anEvent.widget = (nsWidget*)p;
if (aGEK!=nsnull)
{
anEvent.isShift = (aGEK->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
anEvent.isControl = (aGEK->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
anEvent.isAlt = (aGEK->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
// XXX
anEvent.isMeta = PR_FALSE; //(aGEK->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
if(aGEK->length)
anEvent.charCode = nsConvertCharCodeToUnicode(aGEK);
else
anEvent.charCode = 0;
if (anEvent.charCode) {
anEvent.keyCode = 0;
anEvent.isShift = PR_FALSE;
} else
anEvent.keyCode = nsPlatformToDOMKeyCode(aGEK);
#if defined(DEBUG_akkana) || defined(DEBUG_pavlov) || defined (DEBUG_ftang)
printf("Key Press event: keyCode = 0x%x, char code = '%c'",
anEvent.keyCode, anEvent.charCode);
if (anEvent.isShift)
printf(" [shift]");
if (anEvent.isControl)
printf(" [ctrl]");
if (anEvent.isAlt)
printf(" [alt]");
if (anEvent.isMeta)
printf(" [meta]");
printf("\n");
#endif
anEvent.time = aGEK->time;
anEvent.point.x = 0;
anEvent.point.y = 0;
}
}
//=============================================================
void UninitKeyEvent(GdkEventKey *aGEK,
gpointer p,
nsKeyEvent &anEvent,
PRUint32 aEventType)
{
}
/*==============================================================
==============================================================
=============================================================
==============================================================*/
void handle_size_allocate(GtkWidget *w, GtkAllocation *alloc, gpointer p)
{
nsWindow *widget = (nsWindow *)p;
nsSizeEvent event;
InitAllocationEvent(alloc, p, event, NS_SIZE);
NS_ADDREF(widget);
widget->OnResize(event);
NS_RELEASE(widget);
delete event.windowSize;
}
gint handle_expose_event(GtkWidget *w, GdkEventExpose *event, gpointer p)
{
if (event->type == GDK_NO_EXPOSE)
return PR_FALSE;
nsPaintEvent pevent;
InitExposeEvent(event, p, pevent, NS_PAINT);
nsWindow *win = (nsWindow *)p;
win->AddRef();
win->OnExpose(pevent);
win->Release();
UninitExposeEvent(event, p, pevent, NS_PAINT);
return PR_TRUE;
}
//==============================================================
void menu_item_activate_handler(GtkWidget *w, gpointer p)
{
// g_print("menu_item_activate_handler\n");
nsIMenuListener *menuListener = nsnull;
nsIMenuItem *menuItem = (nsIMenuItem *)p;
if (menuItem != nsnull) {
nsMenuEvent mevent;
mevent.message = NS_MENU_SELECTED;
mevent.eventStructType = NS_MENU_EVENT;
mevent.point.x = 0;
mevent.point.y = 0;
// mevent.widget = menuItem;
mevent.widget = nsnull;
menuItem->GetCommand(mevent.mCommand);
mevent.mMenuItem = menuItem;
mevent.time = PR_IntervalNow();
// FIXME - THIS SHOULD WORK. FIX EVENTS FOR XP CODE!!!!! (pav)
// nsEventStatus status;
// mevent.widget->DispatchEvent((nsGUIEvent *)&mevent, status);
menuItem->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
if(menuListener) {
menuListener->MenuItemSelected(mevent);
NS_IF_RELEASE(menuListener);
}
}
}
//==============================================================
void menu_map_handler(GtkWidget *w, gpointer p)
{
nsIMenuListener *menuListener = nsnull;
nsIMenu *menu = (nsIMenu *)p;
if (menu != nsnull) {
nsMenuEvent mevent;
mevent.message = NS_MENU_SELECTED;
mevent.eventStructType = NS_MENU_EVENT;
mevent.point.x = 0;
mevent.point.y = 0;
mevent.widget = nsnull;
mevent.time = PR_IntervalNow();
menu->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
if(menuListener) {
menuListener->MenuConstruct(
mevent,
nsnull, //parent window
nsnull, //menuNode
nsnull ); // webshell
NS_IF_RELEASE(menuListener);
}
}
}
//==============================================================
void menu_unmap_handler(GtkWidget *w, gpointer p)
{
nsIMenuListener *menuListener = nsnull;
nsIMenu *menu = (nsIMenu *)p;
if (menu != nsnull) {
nsMenuEvent mevent;
mevent.message = NS_MENU_SELECTED;
mevent.eventStructType = NS_MENU_EVENT;
mevent.point.x = 0;
mevent.point.y = 0;
mevent.widget = nsnull;
mevent.time = PR_IntervalNow();
menu->QueryInterface(nsIMenuListener::GetIID(), (void**)&menuListener);
if(menuListener) {
menuListener->MenuDestruct(mevent);
NS_IF_RELEASE(menuListener);
}
}
}
//==============================================================
void handle_scrollbar_value_changed(GtkAdjustment *adj, gpointer p)
{
nsScrollbar *widget = (nsScrollbar*) p;
nsScrollbarEvent sevent;
sevent.message = NS_SCROLLBAR_POS;
sevent.widget = (nsWidget *) p;
sevent.eventStructType = NS_SCROLLBAR_EVENT;
GdkWindow *win = (GdkWindow *)widget->GetNativeData(NS_NATIVE_WINDOW);
gdk_window_get_pointer(win, &sevent.point.x, &sevent.point.y, nsnull);
widget->AddRef();
widget->OnScroll(sevent, adj->value);
widget->Release();
/* FIXME we need to set point.* from the event stuff. */
#if 0
nsWindow * widgetWindow = (nsWindow *) p ;
XmScrollBarCallbackStruct * cbs = (XmScrollBarCallbackStruct*) call_data;
sevent.widget = (nsWindow *) p;
if (cbs->event != nsnull) {
sevent.point.x = cbs->event->xbutton.x;
sevent.point.y = cbs->event->xbutton.y;
} else {
sevent.point.x = 0;
sevent.point.y = 0;
}
sevent.time = 0; //XXX Implement this
switch (cbs->reason) {
case XmCR_INCREMENT:
sevent.message = NS_SCROLLBAR_LINE_NEXT;
break;
case XmCR_DECREMENT:
sevent.message = NS_SCROLLBAR_LINE_PREV;
break;
case XmCR_PAGE_INCREMENT:
sevent.message = NS_SCROLLBAR_PAGE_NEXT;
break;
case XmCR_PAGE_DECREMENT:
sevent.message = NS_SCROLLBAR_PAGE_PREV;
break;
case XmCR_DRAG:
sevent.message = NS_SCROLLBAR_POS;
break;
case XmCR_VALUE_CHANGED:
sevent.message = NS_SCROLLBAR_POS;
break;
default:
break;
}
#endif
}
static gint composition_start(GdkEventKey *aEvent, nsWindow *aWin,
nsEventStatus *aStatus) {
nsCompositionEvent compEvent;
compEvent.widget = (nsWidget*)aWin;
compEvent.point.x = 0;
compEvent.point.y = 0;
compEvent.time = aEvent->time;
compEvent.message = NS_COMPOSITION_START;
compEvent.eventStructType = NS_COMPOSITION_START;
compEvent.compositionMessage = NS_COMPOSITION_START;
aWin->DispatchEvent(&compEvent, *aStatus);
// set SpotLocation
aWin->SetXICSpotLocation(compEvent.theReply.mCursorPosition);
return PR_TRUE;
}
static gint composition_draw(GdkEventKey *aEvent, nsWindow *aWin,
nsIUnicodeDecoder *aDecoder,
nsEventStatus *aStatus) {
if (!aWin->mIMECompositionUniString) {
aWin->mIMECompositionUniStringSize = 128;
aWin->mIMECompositionUniString =
new PRUnichar[aWin->mIMECompositionUniStringSize];
}
PRUnichar *uniChar;
PRInt32 uniCharSize;
PRInt32 srcLen = aEvent->length;
for (;;) {
uniChar = aWin->mIMECompositionUniString;
uniCharSize = aWin->mIMECompositionUniStringSize - 1;
aDecoder->Convert((char*)aEvent->string, &srcLen, uniChar, &uniCharSize);
if (srcLen == aEvent->length &&
uniCharSize < aWin->mIMECompositionUniStringSize - 1) {
break;
}
aWin->mIMECompositionUniStringSize += 32;
aWin->mIMECompositionUniString =
new PRUnichar[aWin->mIMECompositionUniStringSize];
}
aWin->mIMECompositionUniString[uniCharSize] = 0;
nsTextEvent textEvent;
textEvent.message = NS_TEXT_EVENT;
textEvent.widget = (nsWidget*)aWin;
textEvent.time = aEvent->time;
textEvent.point.x = 0;
textEvent.point.y = 0;
textEvent.theText = aWin->mIMECompositionUniString;
textEvent.rangeCount = 0;
textEvent.rangeArray = nsnull;
textEvent.isShift = (aEvent->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
textEvent.isControl = (aEvent->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
textEvent.isAlt = (aEvent->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
// XXX
textEvent.isMeta = PR_FALSE; //(aEvent->state & GDK_MOD2_MASK) ? PR_TRUE : PR_FALSE;
textEvent.eventStructType = NS_TEXT_EVENT;
aWin->DispatchEvent(&textEvent, *aStatus);
aWin->SetXICSpotLocation(textEvent.theReply.mCursorPosition);
return True;
}
static gint composition_end(GdkEventKey *aEvent, nsWindow *aWin,
nsEventStatus *aStatus) {
nsCompositionEvent compEvent;
compEvent.widget = (nsWidget*)aWin;
compEvent.point.x = 0;
compEvent.point.y = 0;
compEvent.time = aEvent->time;
compEvent.message = NS_COMPOSITION_END;
compEvent.eventStructType = NS_COMPOSITION_END;
compEvent.compositionMessage = NS_COMPOSITION_END;
aWin->DispatchEvent(&compEvent, *aStatus);
return PR_TRUE;
}
static nsIUnicodeDecoder*
open_unicode_decoder(void) {
nsresult result = NS_ERROR_FAILURE;
nsIUnicodeDecoder *decoder = nsnull;
NS_WITH_SERVICE(nsIPlatformCharset, platform, NS_PLATFORMCHARSET_PROGID,
&result);
if (platform && NS_SUCCEEDED(result)) {
nsAutoString charset("");
result = platform->GetCharset(kPlatformCharsetSel_Menu, charset);
if (NS_FAILED(result) || (charset.Length() == 0)) {
charset = "ISO-8859-1"; // default
}
nsICharsetConverterManager* manager = nsnull;
nsresult res = nsServiceManager::
GetService(kCharsetConverterManagerCID,
nsCOMTypeInfo<nsICharsetConverterManager>::GetIID(),
(nsISupports**)&manager);
if (manager && NS_SUCCEEDED(res)) {
manager->GetUnicodeDecoder(&charset, &decoder);
nsServiceManager::ReleaseService(kCharsetConverterManagerCID, manager);
}
}
return decoder;
}
// GTK's text widget already does XIM, so we don't want to do this again
gint handle_key_press_event_for_text(GtkObject *w, GdkEventKey* event,
gpointer p)
{
nsKeyEvent kevent;
nsTextWidget* win = (nsTextWidget*)p;
// work around for annoying things.
if (event->keyval == GDK_Tab)
if (event->state & GDK_CONTROL_MASK)
if (event->state & GDK_MOD1_MASK)
return PR_FALSE;
// Don't pass shift, control and alt as key press events
if (event->keyval == GDK_Shift_L
|| event->keyval == GDK_Shift_R
|| event->keyval == GDK_Control_L
|| event->keyval == GDK_Control_R)
return PR_TRUE;
win->AddRef();
InitKeyEvent(event, p, kevent, NS_KEY_DOWN);
win->OnKey(kevent);
//
// Second, dispatch the Key event as a key press event w/ a Unicode
// character code. Note we have to check for modifier keys, since
// gtk returns a character value for them
//
InitKeyPressEvent(event,p, kevent);
win->OnKey(kevent);
win->Release();
if (w)
{
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
}
return PR_TRUE;
}
// GTK's text widget already does XIM, so we don't want to do this again
gint handle_key_release_event_for_text(GtkObject *w, GdkEventKey* event,
gpointer p)
{
nsKeyEvent kevent;
nsTextWidget* win = (nsTextWidget*)p;
// Don't pass shift, control and alt as key release events
if (event->keyval == GDK_Shift_L
|| event->keyval == GDK_Shift_R
|| event->keyval == GDK_Control_L
|| event->keyval == GDK_Control_R)
return PR_TRUE;
InitKeyEvent(event, p, kevent, NS_KEY_UP);
win->AddRef();
win->OnKey(kevent);
win->Release();
if (w)
{
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
}
return PR_TRUE;
}
//==============================================================
gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p)
{
nsKeyEvent kevent;
nsWindow* win = (nsWindow*)p;
// work around for annoying things.
if (event->keyval == GDK_Tab)
if (event->state & GDK_CONTROL_MASK)
if (event->state & GDK_MOD1_MASK)
return PR_FALSE;
// Don't pass shift, control and alt as key press events
if (event->keyval == GDK_Shift_L
|| event->keyval == GDK_Shift_R
|| event->keyval == GDK_Control_L
|| event->keyval == GDK_Control_R)
return PR_TRUE;
win->AddRef();
//
// First, dispatch the Key event as a virtual key down event
//
InitKeyEvent(event, p, kevent, NS_KEY_DOWN);
win->OnKey(kevent);
//
// Second, dispatch the Key event as a key press event w/ a Unicode
// character code. Note we have to check for modifier keys, since
// gtk returns a character value for them
//
if (event->length) {
static nsIUnicodeDecoder *decoder = nsnull;
if (!decoder) {
decoder = open_unicode_decoder();
}
if (decoder && (!kevent.keyCode)) {
nsEventStatus status;
composition_start(event, win, &status);
composition_draw(event, win, decoder, &status);
composition_end(event, win, &status);
} else {
InitKeyPressEvent(event,p, kevent);
win->OnKey(kevent);
nsEventStatus status;
composition_start(event, win, &status);
composition_end(event, win, &status);
}
} else { // for Home/End/Up/Down/Left/Right/PageUp/PageDown key
InitKeyPressEvent(event,p, kevent);
win->OnKey(kevent);
}
win->Release();
if (w)
{
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_press_event");
}
return PR_TRUE;
}
//==============================================================
gint handle_key_release_event(GtkObject *w, GdkEventKey* event, gpointer p)
{
// Don't pass shift, control and alt as key release events
if (event->keyval == GDK_Shift_L
|| event->keyval == GDK_Shift_R
|| event->keyval == GDK_Control_L
|| event->keyval == GDK_Control_R)
return PR_TRUE;
nsKeyEvent kevent;
InitKeyEvent(event, p, kevent, NS_KEY_UP);
nsWindow * win = (nsWindow *) p;
win->AddRef();
win->OnKey(kevent);
win->Release();
if (w)
{
gtk_signal_emit_stop_by_name (GTK_OBJECT(w), "key_release_event");
}
return PR_TRUE;
}
//==============================================================
void
handle_gdk_event (GdkEvent *event, gpointer data)
{
GtkObject *object = nsnull;
if (event->any.window)
gdk_window_get_user_data (event->any.window, (void **)&object);
if (object != nsnull &&
GDK_IS_SUPERWIN (object))
{
// It was an event on one of our superwindows
nsWindow *window = (nsWindow *)gtk_object_get_data (object, "nsWindow");
if (gtk_grab_get_current () != nsnull)
{
// A GTK+ grab is in effect. Rewrite the event to point to
// our toplevel, and pass it through.
// XXX: We should actually translate the coordinates
gdk_window_unref (event->any.window);
event->any.window = GTK_WIDGET (window->GetMozArea())->window;
gdk_window_ref (event->any.window);
}
else
{
// Handle it ourselves.
switch (event->type)
{
case GDK_KEY_PRESS:
handle_key_press_event (NULL, &event->key, window);
break;
case GDK_KEY_RELEASE:
handle_key_release_event (NULL, &event->key, window);
break;
default:
window->HandleEvent (event);
}
return;
}
}
gtk_main_do_event (event);
}
//==============================================================
void
handle_xlib_shell_event(GdkSuperWin *superwin, XEvent *event, gpointer p)
{
nsWindow *window = (nsWindow *)p;
switch(event->xany.type) {
case ConfigureNotify:
window->HandleXlibConfigureNotifyEvent(event);
break;
default:
break;
}
}
//==============================================================
void
handle_xlib_bin_event(GdkSuperWin *superwin, XEvent *event, gpointer p)
{
nsWindow *window = (nsWindow *)p;
switch(event->xany.type) {
case Expose:
window->HandleXlibExposeEvent(event);
break;
case ButtonPress:
case ButtonRelease:
window->HandleXlibButtonEvent((XButtonEvent *)event);
break;
case MotionNotify:
window->HandleXlibMotionNotifyEvent((XMotionEvent *) event);
break;
case EnterNotify:
case LeaveNotify:
window->HandleXlibCrossingEvent((XCrossingEvent *) event);
break;
default:
break;
}
}
//==============================================================
gint nsGtkWidget_FSBCancel_Callback(GtkWidget *w, gpointer p)
{
#if 0
nsWindow *widgetWindow = (nsWindow*)gtk_object_get_user_data(GTK_OBJECT(w));
nsFileWidget * widgetWindow = (nsFileWidget *) p ;
if (p != nsnull) {
widgetWindow->OnCancel();
}
#endif
return PR_FALSE;
}
//==============================================================
gint nsGtkWidget_FSBOk_Callback(GtkWidget *w, gpointer p)
{
#if 0
nsWindow *widgetWindow = (nsWindow*)gtk_object_get_user_data(GTK_OBJECT(w));
nsFileWidget * widgetWindow = (nsFileWidget *) p;
if (p != nsnull) {
widgetWindow->OnOk();
}
#endif
return PR_FALSE;
}

View File

@@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsGtkEventHandler_h
#define __nsGtkEventHandler_h
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include "gdksuperwin.h"
class nsIWidget;
class nsIMenuItem;
class nsIMenu;
gint handle_configure_event(GtkWidget *w, GdkEventConfigure *conf, gpointer p);
void handle_size_allocate(GtkWidget *w, GtkAllocation *alloc, gpointer p);
gint handle_expose_event(GtkWidget *w, GdkEventExpose *event, gpointer p);
gint handle_key_release_event_for_text(GtkObject *w, GdkEventKey* event, gpointer p);
gint handle_key_press_event_for_text(GtkObject *w, GdkEventKey* event, gpointer p);
gint handle_key_release_event(GtkObject *w, GdkEventKey* event, gpointer p);
gint handle_key_press_event(GtkObject *w, GdkEventKey* event, gpointer p);
void handle_scrollbar_value_changed(GtkAdjustment *adjustment, gpointer p);
void menu_item_activate_handler(GtkWidget *w, gpointer p);
void menu_map_handler(GtkWidget *w, gpointer p);
void menu_unmap_handler(GtkWidget *w, gpointer p);
//----------------------------------------------------
gint nsGtkWidget_FSBCancel_Callback(GtkWidget *w, gpointer p);
gint nsGtkWidget_FSBOk_Callback(GtkWidget *w, gpointer p);
//----------------------------------------------------
gint CheckButton_Toggle_Callback(GtkWidget *w, gpointer p);
gint nsGtkWidget_RadioButton_ArmCallback(GtkWidget *w, gpointer p);
gint nsGtkWidget_RadioButton_DisArmCallback(GtkWidget *w, gpointer p);
gint nsGtkWidget_Text_Callback(GtkWidget *w, GdkEventKey* event, gpointer p);
gint nsGtkWidget_Expose_Callback(GtkWidget *w, gpointer p);
gint nsGtkWidget_Refresh_Callback(gpointer call_data);
void handle_xlib_shell_event(GdkSuperWin *superwin, XEvent *event, gpointer p);
void handle_xlib_bin_event(GdkSuperWin *superwin, XEvent *event, gpointer p);
void handle_gdk_event (GdkEvent *event, gpointer data);
#endif // __nsGtkEventHandler.h

View File

@@ -0,0 +1,213 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <unistd.h>
#include <string.h>
#include "nsGtkUtils.h"
#include <gdk/gdkx.h>
#include <gdk/gdkprivate.h>
#if defined(__osf__) && !defined(_XOPEN_SOURCE_EXTENDED)
/*
** DEC's compiler requires _XOPEN_SOURCE_EXTENDED to be defined in
** order for it to see the prototype for usleep in unistd.h, but if
** we define that the build breaks long before getting here. So
** put the prototype here explicitly.
*/
int usleep(useconds_t);
#endif
#if defined(__QNX__)
#define usleep(s) sleep(s)
#endif
//////////////////////////////////////////////////////////////////
#if 0
/* staitc */ gint
nsGtkUtils::gdk_query_pointer(GdkWindow * window,
gint * x_out,
gint * y_out)
{
g_return_val_if_fail(NULL != window, FALSE);
g_return_val_if_fail(NULL != x_out, FALSE);
g_return_val_if_fail(NULL != y_out, FALSE);
Window root;
Window child;
int rootx, rooty;
int winx = 0;
int winy = 0;
unsigned int xmask = 0;
gint result = FALSE;
*x_out = -1;
*y_out = -1;
result = XQueryPointer(GDK_WINDOW_XDISPLAY(window),
GDK_WINDOW_XWINDOW(window),
&root,
&child,
&rootx,
&rooty,
&winx,
&winy,
&xmask);
if (result)
{
*x_out = rootx;
*y_out = rooty;
}
return result;
}
#endif
//////////////////////////////////////////////////////////////////
/* static */ void
nsGtkUtils::gtk_widget_set_color(GtkWidget * widget,
GtkRcFlags flags,
GtkStateType state,
GdkColor * color)
{
GtkRcStyle * rc_style;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (color != NULL);
g_return_if_fail (flags == 0);
rc_style = (GtkRcStyle *) gtk_object_get_data (GTK_OBJECT (widget),
"modify-style");
if (!rc_style)
{
rc_style = gtk_rc_style_new ();
gtk_widget_modify_style (widget, rc_style);
gtk_object_set_data (GTK_OBJECT (widget), "modify-style", rc_style);
}
if (flags & GTK_RC_FG)
{
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_FG);
rc_style->fg[state] = *color;
}
if (flags & GTK_RC_BG)
{
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_BG);
rc_style->bg[state] = *color;
}
if (flags & GTK_RC_TEXT)
{
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_TEXT);
rc_style->text[state] = *color;
}
if (flags & GTK_RC_BASE)
{
rc_style->color_flags[state] = GtkRcFlags(rc_style->color_flags[state] | GTK_RC_BASE);
rc_style->base[state] = *color;
}
}
//////////////////////////////////////////////////////////////////
/* static */ GdkModifierType
nsGtkUtils::gdk_keyboard_get_modifiers()
{
GdkModifierType m = (GdkModifierType) 0;
gdk_window_get_pointer(NULL,NULL,NULL,&m);
return m;
}
//////////////////////////////////////////////////////////////////
/* static */ void
nsGtkUtils::gdk_window_flash(GdkWindow * aGdkWindow,
unsigned int aTimes,
unsigned long aInterval,
GdkRectangle * aArea)
{
gint x;
gint y;
gint width;
gint height;
guint i;
GdkGC * gc = 0;
GdkColor white;
gdk_window_get_geometry(aGdkWindow,
NULL,
NULL,
&width,
&height,
NULL);
gdk_window_get_origin (aGdkWindow,
&x,
&y);
gc = gdk_gc_new(GDK_ROOT_PARENT());
white.pixel = WhitePixel(gdk_display,DefaultScreen(gdk_display));
gdk_gc_set_foreground(gc,&white);
gdk_gc_set_function(gc,GDK_XOR);
gdk_gc_set_subwindow(gc,GDK_INCLUDE_INFERIORS);
/*
* If an area is given, use that. Notice how out of whack coordinates
* and dimentsions are not checked!!!
*/
if (aArea)
{
x += aArea->x;
y += aArea->y;
width = aArea->width;
height = aArea->height;
}
/*
* Need to do this twice so that the XOR effect can replace
* the original window contents.
*/
for (i = 0; i < aTimes * 2; i++)
{
gdk_draw_rectangle(GDK_ROOT_PARENT(),
gc,
TRUE,
x,
y,
width,
height);
gdk_flush();
usleep(aInterval);
}
gdk_gc_destroy(gc);
}
//////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsGtkUtils_h
#define __nsGtkUtils_h
#include <gtk/gtk.h>
struct nsGtkUtils
{
//
// Wrapper for XQueryPointer
//
#if 0
static gint gdk_query_pointer(GdkWindow * window,
gint * x_out,
gint * y_out);
#endif
//
// Change a widget's background
//
// flags isa bit mask of the following bits:
//
// GTK_RC_FG
// GTK_RC_BG
// GTK_RC_TEXT
// GTK_RC_BASE
//
// state is an enum:
//
// GTK_STATE_NORMAL,
// GTK_STATE_ACTIVE,
// GTK_STATE_PRELIGHT,
// GTK_STATE_SELECTED,
// GTK_STATE_INSENSITIVE
//
static void gtk_widget_set_color(GtkWidget * widget,
GtkRcFlags flags,
GtkStateType state,
GdkColor * color);
/**
* Return the current keyboard modifier state.
*
* @return the current keyboard modifier state.
*
*/
static GdkModifierType gdk_keyboard_get_modifiers();
/**
* Flash an area within a GDK window (or the whole window)
*
* @param aGdkWindow The GDK window to flash.
* @param aTimes Number of times to flash the area.
* @param aInterval Interval between flashes in milliseconds.
* @param aArea The area to flash. The whole window if NULL.
*
*/
static void gdk_window_flash(GdkWindow * aGdkWindow,
unsigned int aTimes,
unsigned long aInterval,
GdkRectangle * aArea);
};
#endif // __nsGtkEventHandler.h

View File

@@ -0,0 +1,141 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsLabel.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsLabel, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsLabel, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsLabel, nsILabel, nsIWidget)
//-------------------------------------------------------------------------
//
// nsLabel constructor
//
//-------------------------------------------------------------------------
nsLabel::nsLabel() : nsWidget(), nsILabel()
{
NS_INIT_REFCNT();
mAlignment = eAlign_Left;
}
//-------------------------------------------------------------------------
//
// nsLabel destructor
//
//-------------------------------------------------------------------------
nsLabel::~nsLabel()
{
}
//-------------------------------------------------------------------------
//
// Create the nativeLabel widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsLabel::CreateNative(GtkObject *parentWindow)
{
unsigned char alignment = GetNativeAlignment();
mWidget = gtk_label_new("");
gtk_widget_set_name(mWidget, "nsLabel");
gtk_misc_set_alignment(GTK_MISC(mWidget), 0.0, alignment);
return NS_OK;
}
//-------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsLabel::PreCreateWidget(nsWidgetInitData *aInitData)
{
if (nsnull != aInitData) {
nsLabelInitData* data = (nsLabelInitData *) aInitData;
mAlignment = data->mAlignment;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set alignment
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsLabel::SetAlignment(nsLabelAlignment aAlignment)
{
GtkJustification align;
mAlignment = aAlignment;
align = GetNativeAlignment();
gtk_misc_set_alignment(GTK_MISC(mWidget), 0.0, align);
return NS_OK;
}
//-------------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------------
GtkJustification nsLabel::GetNativeAlignment()
{
switch (mAlignment) {
case eAlign_Right : return GTK_JUSTIFY_RIGHT;
case eAlign_Left : return GTK_JUSTIFY_LEFT;
case eAlign_Center: return GTK_JUSTIFY_CENTER;
default :
return GTK_JUSTIFY_LEFT;
}
return GTK_JUSTIFY_LEFT;
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsLabel::SetLabel(const nsString& aText)
{
NS_ALLOC_STR_BUF(label, aText, 256);
gtk_label_set(GTK_LABEL(mWidget), label);
NS_FREE_STR_BUF(label);
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsLabel::GetLabel(nsString& aBuffer)
{
char * text;
gtk_label_get(GTK_LABEL(mWidget), &text);
aBuffer.SetLength(0);
aBuffer.Append(text);
return NS_OK;
}

View File

@@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsLabel_h__
#define nsLabel_h__
#include "nsWidget.h"
#include "nsILabel.h"
/**
* Native GTK+ Label wrapper
*/
class nsLabel : public nsWidget,
public nsILabel
{
public:
nsLabel();
virtual ~nsLabel();
NS_DECL_ISUPPORTS_INHERITED
// nsILabel part
NS_IMETHOD SetLabel(const nsString &aText);
NS_IMETHOD GetLabel(nsString &aBuffer);
NS_IMETHOD SetAlignment(nsLabelAlignment aAlignment);
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
virtual PRBool OnMove(PRInt32 aX, PRInt32 aY) { return PR_FALSE; }
virtual PRBool OnResize(nsRect &aRect) { return PR_FALSE; }
protected:
NS_METHOD CreateNative(GtkObject *parentWindow);
GtkJustification GetNativeAlignment();
nsLabelAlignment mAlignment;
};
#endif // nsLabel_h__

View File

@@ -0,0 +1,394 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsListBox.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsListBox, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsListBox, nsWidget)
NS_IMPL_QUERY_INTERFACE3(nsListBox, nsIListBox, nsIListWidget, nsIWidget)
//-------------------------------------------------------------------------
//
// nsListBox constructor
//
//-------------------------------------------------------------------------
nsListBox::nsListBox() : nsWidget(), nsIListWidget(), nsIListBox()
{
NS_INIT_REFCNT();
mMultiSelect = PR_FALSE;
mCList = nsnull;
}
//-------------------------------------------------------------------------
//
// nsListBox:: destructor
//
//-------------------------------------------------------------------------
nsListBox::~nsListBox()
{
}
void nsListBox::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mCList);
InstallButtonReleaseSignal(mCList);
InstallEnterNotifySignal(mCList);
InstallLeaveNotifySignal(mCList);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mCList,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
}
//-------------------------------------------------------------------------
//
// initializer
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::SetMultipleSelection(PRBool aMultipleSelections)
{
mMultiSelect = aMultipleSelections;
if (mCList) {
if (mMultiSelect)
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_MULTIPLE);
else
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_BROWSE);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// AddItemAt
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::AddItemAt(nsString &aItem, PRInt32 aPosition)
{
if (mCList) {
gchar *text[2];
const nsAutoCString tempStr(aItem);
text[0] = (gchar*)(const char *)tempStr;
text[1] = (gchar*)NULL;
gtk_clist_insert(GTK_CLIST(mCList), (int)aPosition, text);
// XXX Im not sure using the string address is the right thing to
// store in the row data.
gtk_clist_set_row_data(GTK_CLIST(mCList), aPosition, (gpointer)&aItem);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Finds an item at a postion
//
//-------------------------------------------------------------------------
PRInt32 nsListBox::FindItem(nsString &aItem, PRInt32 aStartPos)
{
int i = -1;
if (mCList) {
i = gtk_clist_find_row_from_data(GTK_CLIST(mCList), (gpointer)&aItem);
if (i < aStartPos) {
i = -1;
}
}
return i;
}
//-------------------------------------------------------------------------
//
// CountItems - Get Item Count
//
//-------------------------------------------------------------------------
PRInt32 nsListBox::GetItemCount()
{
if (mCList) {
return GTK_CLIST(mCList)->rows;
}
else {
return 0;
}
}
//-------------------------------------------------------------------------
//
// Removes an Item at a specified location
//
//-------------------------------------------------------------------------
PRBool nsListBox::RemoveItemAt(PRInt32 aPosition)
{
if (mCList) {
gtk_clist_remove(GTK_CLIST(mCList), aPosition);
}
return PR_TRUE;
}
//-------------------------------------------------------------------------
//
//
//
//-------------------------------------------------------------------------
PRBool nsListBox::GetItemAt(nsString& anItem, PRInt32 aPosition)
{
PRBool result = PR_FALSE;
anItem.Truncate();
if (mCList) {
char *text = nsnull;
gtk_clist_get_text(GTK_CLIST(mCList),aPosition,0,&text);
if (text) {
anItem.Append(text);
result = PR_TRUE;
}
}
return result;
}
//-------------------------------------------------------------------------
//
// Gets the selected of selected item
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::GetSelectedItem(nsString& aItem)
{
aItem.Truncate();
if (mCList) {
PRInt32 i=0, idx=-1;
GtkCList *clist = GTK_CLIST(mCList);
GList *list = clist->row_list;
for (i=0; i < clist->rows && idx == -1; i++, list = list->next) {
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
char *text = nsnull;
gtk_clist_get_text(GTK_CLIST(mCList),i,0,&text);
if (text) {
aItem.Append(text);
}
return NS_OK;
}
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Gets the list of selected otems
//
//-------------------------------------------------------------------------
PRInt32 nsListBox::GetSelectedIndex()
{
PRInt32 i=0, idx=-1;
if (mCList) {
if (!mMultiSelect) {
GtkCList *clist = GTK_CLIST(mCList);
GList *list = clist->row_list;
for (i=0; i < clist->rows && idx == -1; i++, list = list->next) {
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
idx = i;
}
}
} else {
NS_ASSERTION(PR_FALSE, "Multi selection list box does not support GetSelectedIndex()");
}
}
return idx;
}
//-------------------------------------------------------------------------
//
// SelectItem
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::SelectItem(PRInt32 aPosition)
{
if (mCList) {
gtk_clist_select_row(GTK_CLIST(mCList), aPosition, 0);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// GetSelectedCount
//
//-------------------------------------------------------------------------
PRInt32 nsListBox::GetSelectedCount()
{
if (mCList) {
if (!GTK_CLIST(mCList)->selection)
return 0;
else
return (PRInt32)g_list_length(GTK_CLIST(mCList)->selection);
}
else {
return 0;
}
}
//-------------------------------------------------------------------------
//
// GetSelectedIndices
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
{
if (mCList) {
PRInt32 i=0, num = 0;
GtkCList *clist = GTK_CLIST(mCList);
GList *list = clist->row_list;
for (i=0; i < clist->rows && num < aSize; i++, list = list->next) {
if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED) {
aIndices[num] = i;
num++;
}
}
}
else {
PRInt32 i = 0;
for (i = 0; i < aSize; i++) aIndices[i] = 0;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// SetSelectedIndices
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::SetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize)
{
if (mCList) {
gtk_clist_unselect_all(GTK_CLIST(mCList));
int i;
for (i=0;i<aSize;i++) {
SelectItem(aIndices[i]);
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Deselect
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::Deselect()
{
if (mCList) {
gtk_clist_unselect_all(GTK_CLIST(mCList));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set initial parameters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::PreCreateWidget(nsWidgetInitData *aInitData)
{
if (nsnull != aInitData) {
nsListBoxInitData* data = (nsListBoxInitData *) aInitData;
mMultiSelect = data->mMultiSelect;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Create the native widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsListBox::CreateNative(GtkObject *parentWindow)
{
// to handle scrolling
mWidget = gtk_scrolled_window_new (nsnull, nsnull);
gtk_widget_set_name(mWidget, "nsListBox");
gtk_container_set_border_width(GTK_CONTAINER(mWidget), 0);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (mWidget),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
mCList = ::gtk_clist_new(1);
gtk_clist_column_titles_hide(GTK_CLIST(mCList));
// Default (it may be changed)
gtk_clist_set_selection_mode(GTK_CLIST(mCList), GTK_SELECTION_BROWSE);
SetMultipleSelection(mMultiSelect);
gtk_widget_show(mCList);
gtk_signal_connect(GTK_OBJECT(mCList),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
gtk_container_add (GTK_CONTAINER (mWidget), mCList);
return NS_OK;
}
void
nsListBox::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mCList) {
mCList = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
//-------------------------------------------------------------------------
//
// set font for listbox
//
//-------------------------------------------------------------------------
/*virtual*/
void nsListBox::SetFontNative(GdkFont *aFont)
{
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
// gtk_style_copy ups the ref count of the font
gdk_font_unref (style->font);
style->font = aFont;
gdk_font_ref(style->font);
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsListBox_h__
#define nsListBox_h__
#include "nsWidget.h"
#include "nsIListBox.h"
/**
* Native GTK+ Listbox wrapper
*/
class nsListBox : public nsWidget,
public nsIListWidget,
public nsIListBox
{
public:
nsListBox();
virtual ~nsListBox();
NS_DECL_ISUPPORTS_INHERITED
// nsIListBox interface
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
NS_IMETHOD SetMultipleSelection(PRBool aMultipleSelections);
NS_IMETHOD AddItemAt(nsString &aItem, PRInt32 aPosition);
PRInt32 FindItem(nsString &aItem, PRInt32 aStartPos);
PRInt32 GetItemCount();
PRBool RemoveItemAt(PRInt32 aPosition);
PRBool GetItemAt(nsString& anItem, PRInt32 aPosition);
NS_IMETHOD GetSelectedItem(nsString& aItem);
PRInt32 GetSelectedIndex();
PRInt32 GetSelectedCount();
NS_IMETHOD GetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
NS_IMETHOD SetSelectedIndices(PRInt32 aIndices[], PRInt32 aSize);
NS_IMETHOD SelectItem(PRInt32 aPosition);
NS_IMETHOD Deselect() ;
virtual void SetFontNative(GdkFont *aFont);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
GtkWidget *mCList;
PRBool mMultiSelect;
};
#endif // nsListBox_h__

View File

@@ -0,0 +1,316 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsLookAndFeel.h"
#include <gtk/gtkinvisible.h>
#define GDK_COLOR_TO_NS_RGB(c) \
((nscolor) NS_RGB(c.red, c.green, c.blue))
NS_IMPL_ISUPPORTS1(nsLookAndFeel, nsILookAndFeel)
//-------------------------------------------------------------------------
//
// Query interface implementation
//
//-------------------------------------------------------------------------
nsLookAndFeel::nsLookAndFeel()
{
NS_INIT_REFCNT();
mWidget = gtk_invisible_new();
gtk_widget_ensure_style(mWidget);
mStyle = gtk_widget_get_style(mWidget);
}
nsLookAndFeel::~nsLookAndFeel()
{
gtk_widget_destroy(mWidget);
}
NS_IMETHODIMP nsLookAndFeel::GetColor(const nsColorID aID, nscolor &aColor)
{
nsresult res = NS_OK;
aColor = 0; // default color black
switch (aID) {
case eColor_WindowBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_WindowForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_WidgetBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_WidgetForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_WidgetSelectBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
break;
case eColor_WidgetSelectForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
break;
case eColor_Widget3DHighlight:
aColor = NS_RGB(0xa0,0xa0,0xa0);
break;
case eColor_Widget3DShadow:
aColor = NS_RGB(0x40,0x40,0x40);
break;
case eColor_TextBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_TextForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_TextSelectBackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
break;
case eColor_TextSelectForeground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_SELECTED]);
break;
// css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
case eColor_activeborder:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_activecaption:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_appworkspace:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_background:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_captiontext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_graytext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
break;
case eColor_highlight:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]);
break;
case eColor_highlighttext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]);
break;
case eColor_inactiveborder:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_inactivecaption:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_INSENSITIVE]);
break;
case eColor_inactivecaptiontext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]);
break;
case eColor_infobackground:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_infotext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_menu:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_menutext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_scrollbar:
break;
case eColor_threedface:
case eColor_buttonface:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_buttonhighlight: // ?
case eColor_threedhighlight:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_ACTIVE]);
break;
case eColor_buttontext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
case eColor_buttonshadow:
case eColor_threeddarkshadow:
case eColor_threedshadow: // i think these should be the same
aColor = NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(NS_DarkenColor(GDK_COLOR_TO_NS_RGB(mStyle->light[GTK_STATE_NORMAL]))))));
// aColor = GDK_COLOR_TO_NS_RGB(mStyle->dark[GTK_STATE_NORMAL]); // dark style gives me bright green?!
break;
case eColor_threedlightshadow:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->light[GTK_STATE_NORMAL]);
break;
case eColor_window:
case eColor_windowframe:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]);
break;
case eColor_windowtext:
aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]);
break;
default:
/* default color is BLACK */
aColor = 0;
res = NS_ERROR_FAILURE;
break;
}
// printf("%i, %i, %i\n", NS_GET_R(aColor), NS_GET_B(aColor), NS_GET_G(aColor));
return res;
}
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
{
nsresult res = NS_OK;
switch (aID) {
case eMetric_WindowTitleHeight:
aMetric = 0;
break;
case eMetric_WindowBorderWidth:
// aMetric = mStyle->klass->xthickness;
break;
case eMetric_WindowBorderHeight:
// aMetric = mStyle->klass->ythickness;
break;
case eMetric_Widget3DBorder:
// aMetric = 4;
break;
case eMetric_TextFieldHeight:
{
GtkRequisition req;
GtkWidget *text = gtk_entry_new();
// needed to avoid memory leak
gtk_widget_ref(text);
gtk_object_sink(GTK_OBJECT(text));
gtk_widget_size_request(text,&req);
aMetric = req.height;
gtk_widget_destroy(text);
gtk_widget_unref(text);
}
break;
case eMetric_TextFieldBorder:
aMetric = 2;
break;
case eMetric_TextVerticalInsidePadding:
aMetric = 0;
break;
case eMetric_TextShouldUseVerticalInsidePadding:
aMetric = 0;
break;
case eMetric_TextHorizontalInsideMinimumPadding:
aMetric = 15;
break;
case eMetric_TextShouldUseHorizontalInsideMinimumPadding:
aMetric = 1;
break;
case eMetric_ButtonHorizontalInsidePaddingNavQuirks:
aMetric = 10;
break;
case eMetric_ButtonHorizontalInsidePaddingOffsetNavQuirks:
aMetric = 8;
break;
case eMetric_CheckboxSize:
aMetric = 15;
break;
case eMetric_RadioboxSize:
aMetric = 15;
break;
case eMetric_ListShouldUseHorizontalInsideMinimumPadding:
aMetric = 15;
break;
case eMetric_ListHorizontalInsideMinimumPadding:
aMetric = 15;
break;
case eMetric_ListShouldUseVerticalInsidePadding:
aMetric = 1;
break;
case eMetric_ListVerticalInsidePadding:
aMetric = 1;
break;
case eMetric_CaretBlinkTime:
aMetric = 500;
break;
case eMetric_CaretWidthTwips:
aMetric = 20;
break;
default:
aMetric = 0;
res = NS_ERROR_FAILURE;
}
return res;
}
NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetric)
{
nsresult res = NS_OK;
switch (aID) {
case eMetricFloat_TextFieldVerticalInsidePadding:
aMetric = 0.25f;
break;
case eMetricFloat_TextFieldHorizontalInsidePadding:
aMetric = 0.95f; // large number on purpose so minimum padding is used
break;
case eMetricFloat_TextAreaVerticalInsidePadding:
aMetric = 0.40f;
break;
case eMetricFloat_TextAreaHorizontalInsidePadding:
aMetric = 0.40f; // large number on purpose so minimum padding is used
break;
case eMetricFloat_ListVerticalInsidePadding:
aMetric = 0.10f;
break;
case eMetricFloat_ListHorizontalInsidePadding:
aMetric = 0.40f;
break;
case eMetricFloat_ButtonVerticalInsidePadding:
aMetric = 0.25f;
break;
case eMetricFloat_ButtonHorizontalInsidePadding:
aMetric = 0.25f;
break;
default:
aMetric = -1.0;
res = NS_ERROR_FAILURE;
}
return res;
}
#ifdef NS_DEBUG
NS_IMETHODIMP nsLookAndFeel::GetNavSize(const nsMetricNavWidgetID aWidgetID,
const nsMetricNavFontID aFontID,
const PRInt32 aFontSize,
nsSize &aSize)
{
aSize.width = 0;
aSize.height = 0;
return NS_ERROR_NOT_IMPLEMENTED;
}
#endif

View File

@@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsLookAndFeel
#define __nsLookAndFeel
#include "nsILookAndFeel.h"
#include <gtk/gtk.h>
class nsLookAndFeel: public nsILookAndFeel {
NS_DECL_ISUPPORTS
public:
nsLookAndFeel();
virtual ~nsLookAndFeel();
NS_IMETHOD GetColor(const nsColorID aID, nscolor &aColor);
NS_IMETHOD GetMetric(const nsMetricID aID, PRInt32 & aMetric);
NS_IMETHOD GetMetric(const nsMetricFloatID aID, float & aMetric);
#ifdef NS_DEBUG
// This method returns the actual (or nearest estimate)
// of the Navigator size for a given form control for a given font
// and font size. This is used in NavQuirks mode to see how closely
// we match its size
NS_IMETHOD GetNavSize(const nsMetricNavWidgetID aWidgetID,
const nsMetricNavFontID aFontID,
const PRInt32 aFontSize,
nsSize &aSize);
#endif
protected:
GtkStyle *mStyle;
GtkWidget *mWidget;
};
#endif

View File

@@ -0,0 +1,792 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsMenu.h"
#include "nsIComponentManager.h"
#include "nsIDOMElement.h"
#include "nsIDOMNode.h"
#include "nsIMenuBar.h"
#include "nsIMenuItem.h"
#include "nsIMenuListener.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
nsresult nsMenu::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenu::GetIID())) {
*aInstancePtr = (void*)(nsIMenu*) this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*)(nsISupports*)(nsIMenu*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIMenuListener::GetIID())) {
*aInstancePtr = (void*)(nsIMenuListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsMenu)
NS_IMPL_RELEASE(nsMenu)
//-------------------------------------------------------------------------
//
// nsMenu constructor
//
//-------------------------------------------------------------------------
nsMenu::nsMenu() : nsIMenu()
{
NS_INIT_REFCNT();
mNumMenuItems = 0;
mMenu = nsnull;
mMenuParent = nsnull;
mMenuBarParent = nsnull;
mListener = nsnull;
mConstructCalled = PR_FALSE;
mDOMNode = nsnull;
mWebShell = nsnull;
mDOMElement = nsnull;
mAccessKey = "_";
}
//-------------------------------------------------------------------------
//
// nsMenu destructor
//
//-------------------------------------------------------------------------
nsMenu::~nsMenu()
{
//g_print("nsMenu::~nsMenu() called\n");
NS_IF_RELEASE(mListener);
// Free our menu items
RemoveAll();
gtk_widget_destroy(mMenu);
mMenu = nsnull;
}
//-------------------------------------------------------------------------
//
// Create the proper widget
//-------------------------------------------------------------------------
NS_METHOD nsMenu::Create(nsISupports *aParent, const nsString &aLabel)
{
if(aParent)
{
nsIMenuBar * menubar = nsnull;
aParent->QueryInterface(nsIMenuBar::GetIID(), (void**) &menubar);
if(menubar)
{
mMenuBarParent = menubar;
NS_RELEASE(menubar);
}
else
{
nsIMenu * menu = nsnull;
aParent->QueryInterface(nsIMenu::GetIID(), (void**) &menu);
if(menu)
{
mMenuParent = menu;
NS_RELEASE(menu);
}
}
}
mLabel = aLabel;
mMenu = gtk_menu_new();
gtk_signal_connect (GTK_OBJECT (mMenu), "map",
GTK_SIGNAL_FUNC(menu_map_handler),
this);
gtk_signal_connect (GTK_OBJECT (mMenu), "unmap",
GTK_SIGNAL_FUNC(menu_unmap_handler),
this);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetParent(nsISupports*& aParent)
{
aParent = nsnull;
if (nsnull != mMenuParent) {
return mMenuParent->QueryInterface(kISupportsIID,
(void**)&aParent);
} else if (nsnull != mMenuBarParent) {
return mMenuBarParent->QueryInterface(kISupportsIID,
(void**)&aParent);
}
return NS_ERROR_FAILURE;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetLabel(nsString &aText)
{
aText = mLabel;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::SetLabel(const nsString &aText)
{
/* we Do GetLabel() when we are adding the menu...
* but we might want to redo this.
*/
mLabel = aText;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetAccessKey(nsString &aText)
{
aText = mAccessKey;
char *foo = mAccessKey.ToNewCString();
#ifdef DEBUG_pavlov
g_print("GetAccessKey returns \"%s\"\n", foo);
#endif
nsCRT::free(foo);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::SetAccessKey(const nsString &aText)
{
mAccessKey = aText;
char *foo = mAccessKey.ToNewCString();
#ifdef DEBUG_pavlov
g_print("SetAccessKey setting to \"%s\"\n", foo);
#endif
nsCRT::free(foo);
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Set enabled state
*
*/
NS_METHOD nsMenu::SetEnabled(PRBool aIsEnabled)
{
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Get enabled state
*
*/
NS_METHOD nsMenu::GetEnabled(PRBool* aIsEnabled)
{
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Query if this is the help menu
*
*/
NS_METHOD nsMenu::IsHelpMenu(PRBool* aIsHelpMenu)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddItem(nsISupports * aItem)
{
if(aItem)
{
nsIMenuItem * menuitem = nsnull;
aItem->QueryInterface(nsIMenuItem::GetIID(),
(void**)&menuitem);
if(menuitem)
{
AddMenuItem(menuitem); // nsMenu now owns this
NS_RELEASE(menuitem);
}
else
{
nsIMenu * menu = nsnull;
aItem->QueryInterface(nsIMenu::GetIID(),
(void**)&menu);
if(menu)
{
AddMenu(menu); // nsMenu now owns this
NS_RELEASE(menu);
}
}
}
return NS_OK;
}
// local method used by nsMenu::AddItem
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddMenuItem(nsIMenuItem * aMenuItem)
{
GtkWidget *widget;
void *voidData;
aMenuItem->GetNativeData(voidData);
widget = GTK_WIDGET(voidData);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
// XXX add aMenuItem to internal data structor list
// Need to be adding an nsISupports *, not nsIMenuItem *
nsISupports * supports = nsnull;
aMenuItem->QueryInterface(kISupportsIID,
(void**)&supports);
{
mMenuItemVoidArray.AppendElement(supports);
mNumMenuItems++;
}
return NS_OK;
}
// local method used by nsMenu::AddItem
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddMenu(nsIMenu * aMenu)
{
nsString Label;
GtkWidget *newmenu=nsnull;
void *voidData=NULL;
aMenu->GetLabel(Label);
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
nsnull,
nsIMenuItem::GetIID(),
(void**)&pnsMenuItem);
if (NS_OK == rv) {
nsISupports * supports = nsnull;
QueryInterface(kISupportsIID, (void**) &supports);
pnsMenuItem->Create(supports, Label, PR_FALSE); //PR_TRUE);
NS_RELEASE(supports);
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
void * menuitem = nsnull;
pnsMenuItem->GetNativeData(menuitem);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), newmenu);
NS_RELEASE(pnsMenuItem);
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddSeparator()
{
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(
kMenuItemCID, nsnull, nsIMenuItem::GetIID(), (void**)&pnsMenuItem);
if (NS_OK == rv) {
nsString tmp = "menuseparator";
nsISupports * supports = nsnull;
QueryInterface(kISupportsIID, (void**) &supports);
pnsMenuItem->Create(supports, tmp, PR_TRUE);
NS_RELEASE(supports);
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
NS_RELEASE(pnsMenuItem);
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetItemCount(PRUint32 &aCount)
{
// this should be right.. does it need to be +1 ?
aCount = g_list_length(GTK_MENU_SHELL(mMenu)->children);
//g_print("nsMenu::GetItemCount = %i\n", aCount);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetItemAt(const PRUint32 aPos,
nsISupports *&aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::InsertItemAt(const PRUint32 aPos,
nsISupports *aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::RemoveItem(const PRUint32 aPos)
{
#if 0
// this may work here better than Removeall(), but i'm not sure how to test this one
nsISupports *item = mMenuItemVoidArray[aPos];
delete item;
mMenuItemVoidArray.RemoveElementAt(aPos);
#endif
/*
gtk_menu_shell_remove (GTK_MENU_SHELL (mMenu), item);
nsCRT::free(labelStr);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
*/
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::RemoveAll()
{
//g_print("nsMenu::RemoveAll()\n");
#if 0
// this doesn't work quite right, but this is about all that should really be needed
int i=0;
nsIMenu *menu = nsnull;
nsIMenuItem *menuitem = nsnull;
nsISupports *item = nsnull;
for (i=mMenuItemVoidArray.Count(); i>0; i--)
{
item = (nsISupports*)mMenuItemVoidArray[i-1];
if(nsnull != item)
{
if (NS_OK == item->QueryInterface(nsIMenuItem::GetIID(), (void**)&menuitem)) {
// we do this twice because we have to do it once for QueryInterface,
// then we want to get rid of it.
// g_print("remove nsMenuItem\n");
NS_RELEASE(menuitem);
NS_RELEASE(item);
menuitem = nsnull;
} else if (NS_OK == item->QueryInterface(nsIMenu::GetIID(), (void**)&menu)) {
// g_print("remove nsMenu\n");
NS_RELEASE(menu);
NS_RELEASE(item);
menu = nsnull;
}
// mMenuItemVoidArray.RemoveElementAt(i-1);
}
}
mMenuItemVoidArray.Clear();
#else
for (int i = mMenuItemVoidArray.Count(); i > 0; i--) {
if(nsnull != mMenuItemVoidArray[i-1]) {
nsIMenuItem * menuitem = nsnull;
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenuItem::GetIID(),
(void**)&menuitem);
if(menuitem) {
void *gtkmenuitem = nsnull;
menuitem->GetNativeData(gtkmenuitem);
if (gtkmenuitem) {
// gtk_widget_ref(GTK_WIDGET(gtkmenuitem));
//gtk_widget_destroy(GTK_WIDGET(gtkmenuitem));
gtk_container_remove (GTK_CONTAINER (mMenu), GTK_WIDGET(gtkmenuitem));
}
} else {
nsIMenu * menu= nsnull;
((nsISupports*)mMenuItemVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(),
(void**)&menu);
if(menu)
{
void * gtkmenu = nsnull;
menu->GetNativeData(&gtkmenu);
if(gtkmenu){
//g_print("gtkmenu removed");
//gtk_menu_item_remove_submenu (GTK_MENU_ITEM (item));
}
}
}
}
}
#endif
//g_print("end RemoveAll\n");
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::GetNativeData(void ** aData)
{
*aData = (void *)mMenu;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::SetNativeData(void * aData)
{
return NS_OK;
}
GtkWidget *nsMenu::GetNativeParent()
{
void * voidData;
if (nsnull != mMenuParent) {
mMenuParent->GetNativeData(&voidData);
} else if (nsnull != mMenuBarParent) {
mMenuBarParent->GetNativeData(voidData);
} else {
return nsnull;
}
return GTK_WIDGET(voidData);
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::AddMenuListener(nsIMenuListener * aMenuListener)
{
mListener = aMenuListener;
NS_ADDREF(mListener);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenu::RemoveMenuListener(nsIMenuListener * aMenuListener)
{
if (aMenuListener == mListener) {
NS_IF_RELEASE(mListener);
}
return NS_OK;
}
//-------------------------------------------------------------------------
// nsIMenuListener interface
//-------------------------------------------------------------------------
nsEventStatus nsMenu::MenuItemSelected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuSelected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenu::MenuSelected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuSelected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenu::MenuDeselected(const nsMenuEvent & aMenuEvent)
{
if (nsnull != mListener) {
mListener->MenuDeselected(aMenuEvent);
}
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenu::MenuConstruct(const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell)
{
//g_print("nsMenu::MenuConstruct called \n");
if(menuNode){
SetDOMNode((nsIDOMNode*)menuNode);
}
if(!aWebShell){
aWebShell = mWebShell;
}
// First open the menu.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->SetAttribute("open", "true");
/// Now get the kids. Retrieve our menupopup child.
nsCOMPtr<nsIDOMNode> menuPopupNode;
mDOMNode->GetFirstChild(getter_AddRefs(menuPopupNode));
while (menuPopupNode) {
nsCOMPtr<nsIDOMElement> menuPopupElement(do_QueryInterface(menuPopupNode));
if (menuPopupElement) {
nsString menuPopupNodeType;
menuPopupElement->GetNodeName(menuPopupNodeType);
if (menuPopupNodeType.Equals("menupopup"))
break;
}
nsCOMPtr<nsIDOMNode> oldMenuPopupNode(menuPopupNode);
oldMenuPopupNode->GetNextSibling(getter_AddRefs(menuPopupNode));
}
if (!menuPopupNode)
return nsEventStatus_eIgnore;
nsCOMPtr<nsIDOMNode> menuitemNode;
menuPopupNode->GetFirstChild(getter_AddRefs(menuitemNode));
unsigned short menuIndex = 0;
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
nsString menuitemName;
menuitemElement->GetNodeName(menuitemNodeType);
if (menuitemNodeType.Equals("menuitem")) {
// LoadMenuItem
LoadMenuItem(this,
menuitemElement,
menuitemNode,
menuIndex,
(nsIWebShell*)aWebShell);
} else if (menuitemNodeType.Equals("menuseparator")) {
AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Load a submenu
LoadSubMenu(this, menuitemElement, menuitemNode);
}
}
++menuIndex;
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenu::MenuDestruct(const nsMenuEvent & aMenuEvent)
{
// Close the node.
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
if (domElement)
domElement->RemoveAttribute("open");
//g_print("nsMenu::MenuDestruct called \n");
mConstructCalled = PR_FALSE;
RemoveAll();
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
/**
* Set DOMNode
*
*/
NS_METHOD nsMenu::SetDOMNode(nsIDOMNode * aMenuNode)
{
mDOMNode = aMenuNode;
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Set DOMElement
*
*/
NS_METHOD nsMenu::SetDOMElement(nsIDOMElement * aMenuElement)
{
mDOMElement = aMenuElement;
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Set WebShell
*
*/
NS_METHOD nsMenu::SetWebShell(nsIWebShell * aWebShell)
{
mWebShell = aWebShell;
return NS_OK;
}
//----------------------------------------
void nsMenu::LoadMenuItem(nsIMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode,
unsigned short menuitemIndex,
nsIWebShell * aWebShell)
{
static const char* NS_STRING_TRUE = "true";
nsString disabled;
nsString menuitemName;
nsString menuitemCmd;
menuitemElement->GetAttribute(nsAutoString("disabled"), disabled);
menuitemElement->GetAttribute(nsAutoString("value"), menuitemName);
menuitemElement->GetAttribute(nsAutoString("cmd"), menuitemCmd);
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID,
nsnull,
nsIMenuItem::GetIID(),
(void**)&pnsMenuItem);
if (NS_OK == rv) {
pnsMenuItem->Create(pParentMenu, menuitemName, PR_FALSE);
nsISupports * supports = nsnull;
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports); // Parent should now own menu item
NS_RELEASE(supports);
if(disabled == NS_STRING_TRUE ) {
pnsMenuItem->SetEnabled(PR_FALSE);
}
// Create MenuDelegate - this is the intermediator inbetween
// the DOM node and the nsIMenuItem
// The nsWebShellWindow wacthes for Document changes and then notifies the
// the appropriate nsMenuDelegate object
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
if (!domElement) {
//return NS_ERROR_FAILURE;
return;
}
nsAutoString cmdAtom("oncommand");
nsString cmdName;
domElement->GetAttribute(cmdAtom, cmdName);
pnsMenuItem->SetCommand(cmdName);
// DO NOT use passed in webshell because of messed up windows dynamic loading
// code.
pnsMenuItem->SetWebShell(mWebShell);
pnsMenuItem->SetDOMElement(domElement);
NS_RELEASE(pnsMenuItem);
}
return;
}
//----------------------------------------
void nsMenu::LoadSubMenu(nsIMenu * pParentMenu,
nsIDOMElement * menuElement,
nsIDOMNode * menuNode)
{
nsString menuName;
menuElement->GetAttribute(nsAutoString("value"), menuName);
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
// Create nsMenu
nsIMenu * pnsMenu = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuCID,
nsnull,
nsIMenu::GetIID(),
(void**)&pnsMenu);
if (NS_OK == rv) {
// Call Create
nsISupports * supports = nsnull;
pParentMenu->QueryInterface(kISupportsIID, (void**) &supports);
pnsMenu->Create(supports, menuName);
NS_RELEASE(supports); // Balance QI
// Set nsMenu Name
pnsMenu->SetLabel(menuName);
supports = nsnull;
pnsMenu->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports); // parent takes ownership
NS_RELEASE(supports);
pnsMenu->SetWebShell(mWebShell);
pnsMenu->SetDOMNode(menuNode);
/*
// Begin menuitem inner loop
unsigned short menuIndex = 0;
nsCOMPtr<nsIDOMNode> menuitemNode;
menuNode->GetFirstChild(getter_AddRefs(menuitemNode));
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
menuitemElement->GetNodeName(menuitemNodeType);
#ifdef DEBUG_saari
printf("Type [%s] %d\n", menuitemNodeType.ToNewCString(), menuitemNodeType.Equals("menuseparator"));
#endif
if (menuitemNodeType.Equals("menuitem")) {
// Load a menuitem
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode, menuIndex, mWebShell);
} else if (menuitemNodeType.Equals("menuseparator")) {
pnsMenu->AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Add a submenu
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
}
}
++menuIndex;
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
*/
}
}

View File

@@ -0,0 +1,120 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsMenu_h__
#define nsMenu_h__
#include "nsIMenu.h"
#include "nsIMenuListener.h"
#include "nsVoidArray.h"
class nsIDOMElement;
class nsIDOMNode;
class nsIMenuBar;
class nsIWebShell;
/**
* Native GTK+ Menu wrapper
*/
class nsMenu : public nsIMenu, public nsIMenuListener
{
public:
nsMenu();
virtual ~nsMenu();
NS_DECL_ISUPPORTS
// nsIMenuListener methods
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
NS_IMETHOD Create(nsISupports * aParent, const nsString &aLabel);
// nsIMenu Methods
NS_IMETHOD GetParent(nsISupports *&aParent);
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetLabel(const nsString &aText);
NS_IMETHOD GetAccessKey(nsString &aText);
NS_IMETHOD SetAccessKey(const nsString &aText);
NS_IMETHOD AddItem(nsISupports * aItem);
NS_IMETHOD AddMenuItem(nsIMenuItem * aMenuItem);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD AddSeparator();
NS_IMETHOD GetItemCount(PRUint32 &aCount);
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
NS_IMETHOD RemoveItem(const PRUint32 aPos);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void** aData);
NS_IMETHOD SetNativeData(void* aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
NS_IMETHOD IsHelpMenu(PRBool* aIsHelp);
NS_IMETHOD SetDOMNode(nsIDOMNode * aMenuNode);
NS_IMETHOD SetDOMElement(nsIDOMElement * aMenuElement);
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
protected:
void LoadMenuItem(
nsIMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode,
unsigned short menuitemIndex,
nsIWebShell * aWebShell);
void LoadSubMenu(
nsIMenu * pParentMenu,
nsIDOMElement * menuElement,
nsIDOMNode * menuNode);
GtkWidget *GetNativeParent();
nsString mLabel;
nsString mAccessKey;
PRUint32 mNumMenuItems;
GtkWidget *mMenu;
nsVoidArray mMenuItemVoidArray;
nsIMenu *mMenuParent;
nsIMenuBar *mMenuBarParent;
nsIMenuListener * mListener;
PRBool mConstructCalled;
nsIDOMNode * mDOMNode;
nsIWebShell * mWebShell;
nsIDOMElement * mDOMElement;
};
#endif // nsMenu_h__

View File

@@ -0,0 +1,354 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsMenuBar.h"
#include "nsMenuItem.h"
#include "nsIComponentManager.h"
#include "nsIDOMNode.h"
#include "nsIMenu.h"
#include "nsIWebShell.h"
#include "nsIWidget.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
#include "nsCOMPtr.h"
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuBarCID, NS_MENUBAR_CID);
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
nsresult nsMenuBar::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenuBar::GetIID())) {
*aInstancePtr = (void*) ((nsIMenuBar*) this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) ((nsISupports*)(nsIMenuBar*) this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIMenuListener::GetIID())) {
*aInstancePtr = (void*) ((nsIMenuListener*)this);
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsMenuBar)
NS_IMPL_RELEASE(nsMenuBar)
//-------------------------------------------------------------------------
//
// nsMenuBar constructor
//
//-------------------------------------------------------------------------
nsMenuBar::nsMenuBar() : nsIMenuBar(), nsIMenuListener()
{
NS_INIT_REFCNT();
mNumMenus = 0;
mMenuBar = nsnull;
mParent = nsnull;
mIsMenuBarAdded = PR_FALSE;
mWebShell = nsnull;
mDOMNode = nsnull;
}
//-------------------------------------------------------------------------
//
// nsMenuBar destructor
//
//-------------------------------------------------------------------------
nsMenuBar::~nsMenuBar()
{
// Release the menus
RemoveAll();
}
//-------------------------------------------------------------------------
//
// Create the proper widget
//
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::Create(nsIWidget *aParent)
{
SetParent(aParent);
mMenuBar = gtk_menu_bar_new();
gtk_widget_show(mMenuBar);
mParent->SetMenuBar(this);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::GetParent(nsIWidget *&aParent)
{
aParent = mParent;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::SetParent(nsIWidget *aParent)
{
mParent = aParent;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
{
nsString Label;
GtkWidget *widget, *nmenu;
void *voidData;
nsISupports * supports = nsnull;
aMenu->QueryInterface(kISupportsIID, (void**)&supports);
if (supports) {
mMenusVoidArray.AppendElement(aMenu);
mNumMenus++;
}
aMenu->GetLabel(Label);
// get access key
nsString accessKey = " ";
aMenu->GetAccessKey(accessKey);
if(accessKey != " ")
{
// munge acess key into name
PRInt32 offset = Label.Find(accessKey);
if(offset != -1)
Label.Insert("_", offset);
}
char *foo = Label.ToNewCString();
g_print("%s\n", foo);
nsCRT::free(foo);
widget = nsMenuItem::CreateLocalized(Label);
gtk_widget_show(widget);
gtk_menu_bar_append (GTK_MENU_BAR (mMenuBar), widget);
aMenu->GetNativeData(&voidData);
nmenu = GTK_WIDGET(voidData);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), nmenu);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::GetMenuCount(PRUint32 &aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::RemoveMenu(const PRUint32 aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::RemoveAll()
{
for (int i = mMenusVoidArray.Count(); i > 0; i--) {
if(nsnull != mMenusVoidArray[i-1]) {
nsIMenu * menu = nsnull;
((nsISupports*)mMenusVoidArray[i-1])->QueryInterface(nsIMenu::GetIID(), (void**)&menu);
if(menu) {
//void * gtkmenu= nsnull;
//menu->GetNativeData(&gtkmenu);
//if(gtkmenu){
// gtk_container_remove (GTK_CONTAINER (mMenuBar), GTK_WIDGET(gtkmenu) );
//}
NS_RELEASE(menu);
g_print("menu release \n");
int num =((nsISupports*)mMenusVoidArray[i-1])->Release();
while(num) {
g_print("menu release again!\n");
num = ((nsISupports*)mMenusVoidArray[i-1])->Release();
}
}
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::GetNativeData(void *& aData)
{
aData = (void *)mMenuBar;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::SetNativeData(void * aData)
{
// Temporary hack for MacOS. Will go away when nsMenuBar handles it's own
// construction
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuBar::Paint()
{
return NS_OK;
}
//-------------------------------------------------------------------------
//
// nsMenuListener interface
//
//-------------------------------------------------------------------------
nsEventStatus nsMenuBar::MenuItemSelected(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenuBar::MenuSelected(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenuBar::MenuDeselected(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenuBar::MenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menubarNode,
void * aWebShell)
{
mWebShell = (nsIWebShell*) aWebShell;
mDOMNode = (nsIDOMNode*)menubarNode;
nsIMenuBar * pnsMenuBar = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuBarCID,
nsnull,
nsIMenuBar::GetIID(),
(void**)&pnsMenuBar);
if (NS_OK == rv) {
if (nsnull != pnsMenuBar) {
pnsMenuBar->Create(aParentWindow);
// set pnsMenuBar as a nsMenuListener on aParentWindow
nsCOMPtr<nsIMenuListener> menuListener;
pnsMenuBar->QueryInterface(nsIMenuListener::GetIID(), getter_AddRefs(menuListener));
aParentWindow->AddMenuListener(menuListener);
nsCOMPtr<nsIDOMNode> menuNode;
((nsIDOMNode*)menubarNode)->GetFirstChild(getter_AddRefs(menuNode));
while (menuNode) {
nsCOMPtr<nsIDOMElement> menuElement(do_QueryInterface(menuNode));
if (menuElement) {
nsString menuNodeType;
nsString menuName;
nsString menuAccessKey = " ";
menuElement->GetNodeName(menuNodeType);
if (menuNodeType.Equals("menu")) {
menuElement->GetAttribute(nsAutoString("value"), menuName);
menuElement->GetAttribute(nsAutoString("accesskey"), menuAccessKey);
// Don't create the menu yet, just add in the top level names
// Create nsMenu
nsIMenu * pnsMenu = nsnull;
rv = nsComponentManager::CreateInstance(kMenuCID, nsnull, nsIMenu::GetIID(), (void**)&pnsMenu);
if (NS_OK == rv) {
// Call Create
nsISupports * supports = nsnull;
pnsMenuBar->QueryInterface(kISupportsIID, (void**) &supports);
pnsMenu->Create(supports, menuName);
NS_RELEASE(supports);
pnsMenu->SetLabel(menuName);
pnsMenu->SetAccessKey(menuAccessKey);
pnsMenu->SetDOMNode(menuNode);
pnsMenu->SetDOMElement(menuElement);
pnsMenu->SetWebShell(mWebShell);
// Make nsMenu a child of nsMenuBar
// nsMenuBar takes ownership of the nsMenu
pnsMenuBar->AddMenu(pnsMenu);
// Release the menu now that the menubar owns it
NS_RELEASE(pnsMenu);
}
}
}
nsCOMPtr<nsIDOMNode> oldmenuNode(menuNode);
oldmenuNode->GetNextSibling(getter_AddRefs(menuNode));
} // end while (nsnull != menuNode)
// Give the aParentWindow this nsMenuBar to hold onto.
// The parent window should take ownership at this point
aParentWindow->SetMenuBar(pnsMenuBar);
// HACK: force a paint for now
pnsMenuBar->Paint();
NS_RELEASE(pnsMenuBar);
} // end if ( nsnull != pnsMenuBar )
}
return nsEventStatus_eIgnore;
return nsEventStatus_eIgnore;
}
nsEventStatus nsMenuBar::MenuDestruct(const nsMenuEvent & aMenuEvent)
{
return nsEventStatus_eIgnore;
}

View File

@@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsMenuBar_h__
#define nsMenuBar_h__
#include "nsIMenuBar.h"
#include "nsIMenuListener.h"
#include "nsVoidArray.h"
class nsIDOMNode;
class nsIWebShell;
class nsIWidget;
/**
* Native GTK+ MenuBar wrapper
*/
class nsMenuBar : public nsIMenuBar, public nsIMenuListener
{
public:
nsMenuBar();
virtual ~nsMenuBar();
// nsIMenuListener interface
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(
const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
NS_DECL_ISUPPORTS
NS_IMETHOD Create(nsIWidget * aParent);
// nsIMenuBar Methods
NS_IMETHOD GetParent(nsIWidget *&aParent);
NS_IMETHOD SetParent(nsIWidget * aParent);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD GetMenuCount(PRUint32 &aCount);
NS_IMETHOD GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
NS_IMETHOD InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
NS_IMETHOD RemoveMenu(const PRUint32 aCount);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD Paint();
NS_IMETHOD SetNativeData(void* aData);
protected:
GtkWidget * mMenuBar;
nsIWidget * mParent;
PRBool mIsMenuBarAdded;
nsIWebShell * mWebShell;
nsIDOMNode * mDOMNode;
nsVoidArray mMenusVoidArray;
PRUint32 mNumMenus;
};
#endif // nsMenuBar_h__

View File

@@ -0,0 +1,539 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsMenuItem.h"
#include "nsIMenu.h"
#include "nsIMenuBar.h"
#include "nsIWidget.h"
#include "nsGtkEventHandler.h"
#include "nsIPopUpMenu.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
#include "nsIContentViewer.h"
#include "nsIDOMElement.h"
#include "nsIDocumentViewer.h"
#include "nsIPresContext.h"
#include "nsIWebShell.h"
#include "nsICharsetConverterManager.h"
#include "nsIPlatformCharset.h"
#include "nsIServiceManager.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
nsresult nsMenuItem::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(nsIMenuItem::GetIID())) {
*aInstancePtr = (void*)(nsIMenuItem*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*)(nsISupports*)(nsIMenuItem*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsIMenuListener::GetIID())) {
*aInstancePtr = (void*)(nsIMenuListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsMenuItem)
NS_IMPL_RELEASE(nsMenuItem)
//-------------------------------------------------------------------------
//
// nsMenuItem constructor
//
//-------------------------------------------------------------------------
nsMenuItem::nsMenuItem() : nsIMenuItem()
{
NS_INIT_REFCNT();
mMenuItem = nsnull;
mMenuParent = nsnull;
mPopUpParent = nsnull;
mTarget = nsnull;
mXULCommandListener = nsnull;
mIsSeparator = PR_FALSE;
mWebShell = nsnull;
mDOMElement = nsnull;
mIsSubMenu = PR_FALSE;
}
//-------------------------------------------------------------------------
//
// nsMenuItem destructor
//
//-------------------------------------------------------------------------
nsMenuItem::~nsMenuItem()
{
//g_print("nsMenuItem::~nsMenuItem called\n");
//NS_IF_RELEASE(mTarget);
gtk_widget_destroy(mMenuItem);
mMenuItem = nsnull;
//g_print("end nsMenuItem::~nsMenuItem\n");
}
//-------------------------------------------------------------------------
GtkWidget *nsMenuItem::GetNativeParent()
{
void * voidData;
if (nsnull != mMenuParent) {
mMenuParent->GetNativeData(&voidData);
} else if (nsnull != mPopUpParent) {
mPopUpParent->GetNativeData(voidData);
} else {
return nsnull;
}
return GTK_WIDGET(voidData);
}
//-------------------------------------------------------------------------
nsIWidget * nsMenuItem::GetMenuBarParent(nsISupports * aParent)
{
nsIWidget * widget = nsnull; // MenuBar's Parent
nsIMenu * menu = nsnull;
nsIMenuBar * menuBar = nsnull;
nsIPopUpMenu * popup = nsnull;
nsISupports * parent = aParent;
while(1) {
if (NS_OK == parent->QueryInterface(nsIMenu::GetIID(),(void**)&menu)) {
NS_RELEASE(parent);
if (NS_OK != menu->GetParent(parent)) {
NS_RELEASE(menu);
return nsnull;
}
NS_RELEASE(menu);
} else if (NS_OK == parent->QueryInterface(nsIPopUpMenu::GetIID(),(void**)&popup)) {
if (NS_OK != popup->GetParent(widget)) {
widget = nsnull;
}
NS_RELEASE(popup);
NS_RELEASE(parent);
return widget;
} else if (NS_OK == parent->QueryInterface(nsIMenuBar::GetIID(),(void**)&menuBar)) {
if (NS_OK != menuBar->GetParent(widget)) {
widget = nsnull;
}
NS_RELEASE(menuBar);
NS_RELEASE(parent);
return widget;
} else {
NS_RELEASE(parent);
return nsnull;
}
}
return nsnull;
}
GtkWidget*
nsMenuItem::CreateLocalized(const nsString& aLabel)
{
nsresult result;
static nsIUnicodeEncoder* converter = nsnull;
static int isLatin1 = 0;
static int initialized = 0;
if (!initialized) {
initialized = 1;
result = NS_ERROR_FAILURE;
NS_WITH_SERVICE(nsIPlatformCharset, platform, NS_PLATFORMCHARSET_PROGID,
&result);
if (platform && NS_SUCCEEDED(result)) {
nsAutoString charset("");
result = platform->GetCharset(kPlatformCharsetSel_Menu, charset);
if (NS_SUCCEEDED(result) && (charset.Length() > 0)) {
if (!charset.Compare("iso-8859-1", PR_TRUE)) {
isLatin1 = 1;
}
NS_WITH_SERVICE(nsICharsetConverterManager, manager,
NS_CHARSETCONVERTERMANAGER_PROGID, &result);
if (manager && NS_SUCCEEDED(result)) {
result = manager->GetUnicodeEncoder(&charset, &converter);
if (NS_FAILED(result) && converter) {
NS_RELEASE(converter);
converter = nsnull;
}
else if (converter) {
result = converter->SetOutputErrorBehavior(
nsIUnicodeEncoder::kOnError_Replace, nsnull, '?');
}
}
}
}
}
GtkWidget* menuItem = nsnull;
if (converter) {
char labelStr[128];
labelStr[0] = 0;
PRInt32 srcLen = aLabel.Length() + 1;
PRInt32 destLen = sizeof(labelStr);
result = converter->Convert(aLabel.GetUnicode(), &srcLen, labelStr,
&destLen);
if (labelStr[0] && NS_SUCCEEDED(result)) {
menuItem = gtk_menu_item_new_with_label(labelStr);
if (menuItem && (!isLatin1)) {
GtkWidget* label = GTK_BIN(menuItem)->child;
gtk_widget_ensure_style(label);
GtkStyle* style = gtk_style_copy(label->style);
gdk_font_unref(style->font);
style->font = gdk_fontset_load("*");
gtk_widget_set_style(label, style);
gtk_style_unref(style);
}
}
}
else {
char labelStr[128];
aLabel.ToCString(labelStr, sizeof(labelStr));
menuItem = gtk_menu_item_new_with_label(labelStr);
}
return menuItem;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::Create(nsISupports *aParent,
const nsString &aLabel,
PRBool aIsSeparator)
{
if (nsnull == aParent) {
return NS_ERROR_FAILURE;
}
if(aParent) {
nsIMenu * menu;
aParent->QueryInterface(nsIMenu::GetIID(), (void**) &menu);
mMenuParent = menu;
NS_RELEASE(menu);
}
nsIWidget *widget = nsnull; // MenuBar's Parent
nsISupports *sups;
if (NS_OK == aParent->QueryInterface(kISupportsIID,(void**)&sups)) {
widget = GetMenuBarParent(sups);
// GetMenuBarParent will call release for us
// NS_RELEASE(sups);
mTarget = widget;
}
mIsSeparator = aIsSeparator;
mLabel = aLabel;
// create the native menu item
if(mIsSeparator) {
mMenuItem = gtk_menu_item_new();
} else {
mMenuItem = CreateLocalized(aLabel);
}
gtk_widget_show(mMenuItem);
gtk_signal_connect(GTK_OBJECT(mMenuItem), "activate",
GTK_SIGNAL_FUNC(menu_item_activate_handler),
this);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetLabel(nsString &aText)
{
aText = mLabel;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetLabel(nsString &aText)
{
mLabel = aText;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetEnabled(PRBool aIsEnabled)
{
gtk_widget_set_sensitive(GTK_WIDGET(mMenuItem), aIsEnabled);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetEnabled(PRBool *aIsEnabled)
{
*aIsEnabled = GTK_WIDGET_IS_SENSITIVE(mMenuItem);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetChecked(PRBool aIsEnabled)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetChecked(PRBool *aIsEnabled)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetCheckboxType(PRBool aIsCheckbox)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetCheckboxType(PRBool *aIsCheckbox)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetCommand(PRUint32 & aCommand)
{
aCommand = mCommand;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetTarget(nsIWidget *& aTarget)
{
aTarget = mTarget;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetNativeData(void *& aData)
{
aData = (void *)mMenuItem;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::AddMenuListener(nsIMenuListener * aMenuListener)
{
NS_IF_RELEASE(mXULCommandListener);
NS_IF_ADDREF(aMenuListener);
mXULCommandListener = aMenuListener;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::RemoveMenuListener(nsIMenuListener * aMenuListener)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::IsSeparator(PRBool & aIsSep)
{
aIsSep = mIsSeparator;
return NS_OK;
}
//-------------------------------------------------------------------------
// nsIMenuListener interface
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuItemSelected(const nsMenuEvent & aMenuEvent)
{
if(!mIsSeparator) {
//g_print("nsMenuItem::MenuItemSelected\n");
DoCommand();
}else{
//g_print("nsMenuItem::MenuItemSelected is separator\n");
}
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuSelected(const nsMenuEvent & aMenuEvent)
{
if(mXULCommandListener)
return mXULCommandListener->MenuSelected(aMenuEvent);
//g_print("nsMenuItem::MenuSelected\n");
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuDeselected(const nsMenuEvent &aMenuEvent)
{
//g_print("nsMenuItem::MenuDeselected\n");
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuConstruct(const nsMenuEvent &aMenuEvent,
nsIWidget *aParentWindow,
void *menuNode,
void *aWebShell)
{
//g_print("nsMenuItem::MenuConstruct\n");
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
nsEventStatus nsMenuItem::MenuDestruct(const nsMenuEvent &aMenuEvent)
{
//g_print("nsMenuItem::MenuDestruct\n");
return nsEventStatus_eIgnore;
}
//-------------------------------------------------------------------------
/**
* Sets the JavaScript Command to be invoked when a "gui" event
* occurs on a source widget
* @param aStrCmd the JS command to be cached for later execution
* @return NS_OK
*/
NS_METHOD nsMenuItem::SetCommand(const nsString &aStrCmd)
{
return NS_OK;
}
//-------------------------------------------------------------------------
/**
* Executes the "cached" JavaScript Command
* @return NS_OK if the command was executed properly, otherwise an error code
*/
NS_METHOD nsMenuItem::DoCommand()
{
nsresult rv = NS_ERROR_FAILURE;
if(!mWebShell || !mDOMElement)
return rv;
nsCOMPtr<nsIContentViewer> contentViewer;
NS_ENSURE_SUCCESS(mWebShell->GetContentViewer(getter_AddRefs(contentViewer)),
NS_ERROR_FAILURE);
nsCOMPtr<nsIDocumentViewer> docViewer;
docViewer = do_QueryInterface(contentViewer);
if (!docViewer) {
NS_ERROR("Document viewer interface not supported by the content viewer.");
//g_print("Document viewer interface not supported by the content viewer.");
return rv;
}
nsCOMPtr<nsIPresContext> presContext;
if (NS_FAILED(rv = docViewer->GetPresContext(*getter_AddRefs(presContext)))) {
NS_ERROR("Unable to retrieve the doc viewer's presentation context.");
//g_print("Unable to retrieve the doc viewer's presentation context.");
return rv;
}
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_MOUSE_EVENT;
event.message = NS_MENU_ACTION;
nsCOMPtr<nsIContent> contentNode;
contentNode = do_QueryInterface(mDOMElement);
if (!contentNode) {
NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
//g_print("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
return rv;
}
rv = contentNode->HandleDOMEvent(*presContext, &event, nsnull, NS_EVENT_FLAG_INIT, status);
//g_print("HandleDOMEvent called");
return rv;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetDOMNode(nsIDOMNode * aDOMNode)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetDOMNode(nsIDOMNode ** aDOMNode)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetDOMElement(nsIDOMElement * aDOMElement)
{
mDOMElement = aDOMElement;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::GetDOMElement(nsIDOMElement ** aDOMElement)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsMenuItem::SetWebShell(nsIWebShell * aWebShell)
{
mWebShell = aWebShell;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsMenuItem::SetShortcutChar(const nsString &aText)
{
mKeyEquivalent = aText;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsMenuItem::GetShortcutChar(nsString &aText)
{
aText = mKeyEquivalent;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsMenuItem::SetModifiers(PRUint8 aModifiers)
{
mModifiers = aModifiers;
return NS_OK;
}
//----------------------------------------------------------------------
NS_IMETHODIMP nsMenuItem::GetModifiers(PRUint8 * aModifiers)
{
*aModifiers = mModifiers;
return NS_OK;
}

View File

@@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsMenuItem_h__
#define nsMenuItem_h__
#include "nsIMenuItem.h"
#include "nsString.h"
#include "nsIMenuListener.h"
class nsIDOMNode;
class nsIDOMElement;
class nsIMenu;
class nsIPopUpMenu;
class nsIWebShell;
class nsIWidget;
/**
* Native GTK+ MenuItem wrapper
*/
class nsMenuItem : public nsIMenuItem, public nsIMenuListener
{
public:
nsMenuItem();
virtual ~nsMenuItem();
// nsISupports
NS_DECL_ISUPPORTS
// nsIMenuItem Methods
NS_IMETHOD Create(nsISupports *aParent,
const nsString &aLabel,
PRBool aIsSeparator);
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetLabel(nsString &aText);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool *aIsEnabled);
NS_IMETHOD SetChecked(PRBool aIsEnabled);
NS_IMETHOD GetChecked(PRBool *aIsEnabled);
NS_IMETHOD SetCheckboxType(PRBool aIsCheckbox);
NS_IMETHOD GetCheckboxType(PRBool *aIsCheckbox);
NS_IMETHOD GetCommand(PRUint32 & aCommand);
NS_IMETHOD GetTarget(nsIWidget *& aTarget);
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD AddMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD RemoveMenuListener(nsIMenuListener * aMenuListener);
NS_IMETHOD IsSeparator(PRBool & aIsSep);
NS_IMETHOD SetCommand(const nsString & aStrCmd);
NS_IMETHOD DoCommand();
NS_IMETHOD SetDOMNode(nsIDOMNode * aDOMNode);
NS_IMETHOD GetDOMNode(nsIDOMNode ** aDOMNode);
NS_IMETHOD SetDOMElement(nsIDOMElement * aDOMElement);
NS_IMETHOD GetDOMElement(nsIDOMElement ** aDOMElement);
NS_IMETHOD SetWebShell(nsIWebShell * aWebShell);
NS_IMETHOD SetShortcutChar(const nsString &aText);
NS_IMETHOD GetShortcutChar(nsString &aText);
NS_IMETHOD SetModifiers(PRUint8 aModifiers);
NS_IMETHOD GetModifiers(PRUint8 * aModifiers);
// nsIMenuListener interface
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuDeselected(const nsMenuEvent & aMenuEvent);
nsEventStatus MenuConstruct(const nsMenuEvent & aMenuEvent,
nsIWidget * aParentWindow,
void * menuNode,
void * aWebShell);
nsEventStatus MenuDestruct(const nsMenuEvent & aMenuEvent);
static GtkWidget* CreateLocalized(const nsString& aLabel);
protected:
nsIWidget *GetMenuBarParent(nsISupports * aParentSupports);
GtkWidget *GetNativeParent();
nsIMenuListener *mXULCommandListener;
nsString mLabel;
nsString mKeyEquivalent;
PRUint8 mModifiers;
PRUint32 mCommand;
nsIMenu *mMenuParent;
nsIPopUpMenu *mPopUpParent;
nsIWidget *mTarget;
GtkWidget *mMenuItem; // native cascade widget
PRBool mIsSeparator;
PRBool mIsSubMenu;
nsIWebShell * mWebShell;
nsIDOMElement * mDOMElement;
};
#endif // nsMenuItem_h__

View File

@@ -0,0 +1,214 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsPopUpMenu.h"
#include "nsIMenu.h"
#include "nsIWidget.h"
#include "nsString.h"
#include "nsFileSpec.h" // XXX: For nsAutoCString
NS_IMPL_ISUPPORTS(nsPopUpMenu, nsIPopUpMenu::GetIID())
//-------------------------------------------------------------------------
//
// nsPopUpMenu constructor
//
//-------------------------------------------------------------------------
nsPopUpMenu::nsPopUpMenu() : nsIPopUpMenu()
{
NS_INIT_REFCNT();
mNumMenuItems = 0;
mParent = nsnull;
mMenu = nsnull;
}
//-------------------------------------------------------------------------
//
// nsPopUpMenu destructor
//
//-------------------------------------------------------------------------
nsPopUpMenu::~nsPopUpMenu()
{
NS_IF_RELEASE(mParent);
}
//-------------------------------------------------------------------------
//
// Create the proper widget
//
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::Create(nsIWidget *aParent)
{
mParent = aParent;
NS_ADDREF(mParent);
mMenu = gtk_menu_new();
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::AddItem(const nsString &aText)
{
GtkWidget *widget;
widget = gtk_menu_item_new_with_label ((const char*)nsAutoCString(mLabel));
gtk_widget_show(widget);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::AddItem(nsIMenuItem * aMenuItem)
{
GtkWidget *widget;
void *voidData;
aMenuItem->GetNativeData(voidData);
widget = GTK_WIDGET(voidData);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
// XXX add aMenuItem to internal data structor list
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::AddMenu(nsIMenu * aMenu)
{
nsString Label;
GtkWidget *item=NULL, *parentmenu=NULL, *newmenu=NULL;
void *voidData=NULL;
aMenu->GetLabel(Label);
GetNativeData(voidData);
parentmenu = GTK_WIDGET(voidData);
item = gtk_menu_item_new_with_label ((const char*)nsAutoCString(Label));
gtk_widget_show(item);
gtk_menu_shell_append (GTK_MENU_SHELL (parentmenu), item);
voidData = NULL;
aMenu->GetNativeData(&voidData);
newmenu = GTK_WIDGET(voidData);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), newmenu);
// XXX add aMenu to internal data structor list
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::AddSeparator()
{
GtkWidget *widget;
widget = gtk_menu_item_new ();
gtk_widget_show(widget);
gtk_menu_shell_append (GTK_MENU_SHELL (mMenu), widget);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::GetItemCount(PRUint32 &aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::GetItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::InsertItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::InsertItemAt(const PRUint32 aCount, const nsString & aMenuItemName)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::InsertSeparator(const PRUint32 aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::RemoveItem(const PRUint32 aCount)
{
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::RemoveAll()
{
return NS_OK;
}
//-------------------------------------------------------------------------
void nsPopUpMenu::GetXY(GtkMenu *menu, gint *x, gint *y, gpointer user_data)
{
*x = ((nsPopUpMenu *)(user_data))->mX;
*y = ((nsPopUpMenu *)(user_data))->mY;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::ShowMenu(PRInt32 aX, PRInt32 aY)
{
mX = aX;
mY = aY;
gtk_menu_popup (GTK_MENU(mMenu),
NULL,
NULL,
GetXY,
this,
0,
GDK_CURRENT_TIME);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::GetNativeData(void *& aData)
{
aData = (void *)mMenu;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_METHOD nsPopUpMenu::GetParent(nsIWidget *& aParent)
{
aParent = mParent;
return NS_OK;
}

View File

@@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsPopUpMenu_h__
#define nsPopUpMenu_h__
#include "nsIPopUpMenu.h"
#include <gtk/gtk.h>
class nsIWidget;
/**
* Native GTK+ PopUp wrapper
*/
class nsPopUpMenu : public nsIPopUpMenu
{
public:
nsPopUpMenu();
virtual ~nsPopUpMenu();
NS_DECL_ISUPPORTS
NS_IMETHOD Create(nsIWidget * aParent);
// nsIPopUpMenu Methods
NS_IMETHOD AddItem(const nsString &aText);
NS_IMETHOD AddItem(nsIMenuItem * aMenuItem);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD AddSeparator();
NS_IMETHOD GetItemCount(PRUint32 &aCount);
NS_IMETHOD GetItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aCount, nsIMenuItem *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aCount, const nsString & aMenuItemName);
NS_IMETHOD InsertSeparator(const PRUint32 aCount);
NS_IMETHOD RemoveItem(const PRUint32 aCount);
NS_IMETHOD RemoveAll();
static void GetXY(GtkMenu *menu, gint *x, gint *y, gpointer user_data);
NS_IMETHOD ShowMenu(PRInt32 aX, PRInt32 aY);
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD GetParent(nsIWidget*& aParent);
protected:
nsString mLabel;
PRUint32 mNumMenuItems;
nsIWidget *mParent;
GtkWidget *mMenu;
gint mX;
gint mY;
};
#endif // nsPopUpMenu_h__

View File

@@ -0,0 +1,240 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsRadioButton.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
NS_IMPL_ADDREF_INHERITED(nsRadioButton, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsRadioButton, nsWidget)
//-------------------------------------------------------------------------
//
// nsRadioButton constructor
//
//-------------------------------------------------------------------------
nsRadioButton::nsRadioButton() : nsWidget(), nsIRadioButton()
{
NS_INIT_REFCNT();
mLabel = nsnull;
mRadioButton = nsnull;
}
//-------------------------------------------------------------------------
//
// nsRadioButton destructor
//
//-------------------------------------------------------------------------
nsRadioButton::~nsRadioButton()
{
#if 0
if (mLabel)
gtk_widget_destroy(mLabel);
#endif
}
//-------------------------------------------------------------------------
//
// Query interface implementation
//
//-------------------------------------------------------------------------
nsresult nsRadioButton::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
nsresult result = nsWidget::QueryInterface(aIID, aInstancePtr);
if (result == NS_NOINTERFACE && aIID.Equals(nsIRadioButton::GetIID())) {
*aInstancePtr = (void*) ((nsIRadioButton*)this);
AddRef();
result = NS_OK;
}
return result;
}
//-------------------------------------------------------------------------
//
// Create the native RadioButton widget
//
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::CreateNative(GtkObject *parentWindow)
{
mWidget = gtk_event_box_new();
mRadioButton = gtk_radio_button_new(nsnull);
gtk_container_add(GTK_CONTAINER(mWidget), mRadioButton);
gtk_widget_show(mRadioButton);
gtk_widget_set_name(mWidget, "nsRadioButton");
gtk_radio_button_set_group(GTK_RADIO_BUTTON(mRadioButton), nsnull);
gtk_signal_connect(GTK_OBJECT(mRadioButton),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
return NS_OK;
}
void
nsRadioButton::OnDestroySignal(GtkWidget* aGtkWidget)
{
if (aGtkWidget == mLabel) {
mLabel = nsnull;
}
else if (aGtkWidget == mRadioButton) {
mRadioButton = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
void nsRadioButton::InitCallbacks(char * aName)
{
InstallButtonPressSignal(mRadioButton);
InstallButtonReleaseSignal(mRadioButton);
InstallEnterNotifySignal(mWidget);
InstallLeaveNotifySignal(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::SetState(const PRBool aState)
{
if (mWidget) {
GtkToggleButton * item = GTK_TOGGLE_BUTTON(mRadioButton);
item->active = (gboolean) aState;
gtk_widget_queue_draw(GTK_WIDGET(item));
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set this button state
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::GetState(PRBool& aState)
{
if (mWidget) {
aState = (PRBool) GTK_TOGGLE_BUTTON(mRadioButton)->active;
}
else {
aState = PR_TRUE;
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::SetLabel(const nsString& aText)
{
if (mWidget) {
NS_ALLOC_STR_BUF(label, aText, 256);
g_print("nsRadioButton::SetLabel(%s)\n",label);
if (mLabel) {
gtk_label_set(GTK_LABEL(mLabel), label);
} else {
mLabel = gtk_label_new(label);
gtk_misc_set_alignment (GTK_MISC (mLabel), 0.0, 0.5);
gtk_container_add(GTK_CONTAINER(mRadioButton), mLabel);
gtk_widget_show(mLabel); /* XXX */
gtk_signal_connect(GTK_OBJECT(mLabel),
"destroy",
GTK_SIGNAL_FUNC(DestroySignal),
this);
}
NS_FREE_STR_BUF(label);
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get this button label
//
//-------------------------------------------------------------------------
NS_METHOD nsRadioButton::GetLabel(nsString& aBuffer)
{
aBuffer.Truncate();
if (mWidget) {
if (mLabel) {
char* text;
gtk_label_get(GTK_LABEL(mLabel), &text);
aBuffer.Append(text);
}
}
return NS_OK;
}
//////////////////////////////////////////////////////////////////////
// SetBackgroundColor for RadioButton
/*virtual*/
void nsRadioButton::SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark)
{
// use same style copy as SetFont
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
style->bg[GTK_STATE_NORMAL]=*aColorNor;
// Mouse over button
style->bg[GTK_STATE_PRELIGHT]=*aColorBri;
// Button is down
style->bg[GTK_STATE_ACTIVE]=*aColorDark;
// other states too? (GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT,
// GTK_STATE_SELECTED, GTK_STATE_INSENSITIVE)
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
// set style for eventbox too
gtk_widget_set_style(mWidget, style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsRadioButton_h__
#define nsRadioButton_h__
#include "nsWidget.h"
#include "nsIRadioButton.h"
/**
* Native GTK+ Radiobutton wrapper
*/
class nsRadioButton : public nsWidget,
public nsIRadioButton
{
public:
nsRadioButton();
virtual ~nsRadioButton();
// nsISupports
NS_IMETHOD_(nsrefcnt) AddRef();
NS_IMETHOD_(nsrefcnt) Release();
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
// nsIRadioButton part
NS_IMETHOD SetLabel(const nsString& aText);
NS_IMETHOD GetLabel(nsString& aBuffer);
NS_IMETHOD SetState(const PRBool aState);
NS_IMETHOD GetState(PRBool& aState);
virtual PRBool OnMove(PRInt32 aX, PRInt32 aY) { return PR_FALSE; }
virtual PRBool OnPaint(nsPaintEvent & aEvent) { return PR_FALSE; }
virtual PRBool OnResize(nsRect &aRect) { return PR_FALSE; }
// These are needed to Override the auto check behavior
void Armed();
void DisArmed();
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
// Sets background for checkbutton
virtual void SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark);
GtkWidget *mLabel;
GtkWidget *mRadioButton;
};
#endif // nsRadioButton_h__

View File

@@ -0,0 +1,455 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsScrollbar.h"
#include "nsGUIEvent.h"
#include "nsGtkEventHandler.h"
NS_IMPL_ADDREF_INHERITED(nsScrollbar, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsScrollbar, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsScrollbar, nsIScrollbar, nsIWidget)
//-------------------------------------------------------------------------
//
// nsScrollbar constructor
//
//-------------------------------------------------------------------------
nsScrollbar::nsScrollbar (PRBool aIsVertical):nsWidget (), nsIScrollbar ()
{
NS_INIT_REFCNT ();
mOrientation = (aIsVertical) ?
GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL;
}
//-------------------------------------------------------------------------
//
// nsScrollbar destructor
//
//-------------------------------------------------------------------------
nsScrollbar::~nsScrollbar ()
{
}
//-------------------------------------------------------------------------
//
// Create the native scrollbar widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::CreateNative (GtkObject * parentWindow)
{
// Create scrollbar, random default values
mAdjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 100, 1, 25, 25));
#ifdef USE_SUPERWIN
if (!GDK_IS_SUPERWIN(parentWindow)) {
g_print("Damn, brother. That's not a superwin.\n");
return NS_ERROR_FAILURE;
}
GdkSuperWin *superwin = GDK_SUPERWIN(parentWindow);
mMozBox = gtk_mozbox_new(superwin->bin_window);
#endif /* USE_SUPERWIN */
switch (mOrientation)
{
case GTK_ORIENTATION_HORIZONTAL:
mWidget = gtk_hscrollbar_new (mAdjustment);
break;
case GTK_ORIENTATION_VERTICAL:
mWidget = gtk_vscrollbar_new (mAdjustment);
break;
}
#ifdef USE_SUPERWIN
// make sure that we put the scrollbar into the mozbox
gtk_container_add(GTK_CONTAINER(mMozBox), mWidget);
#endif /* USE_SUPERWIN */
gtk_widget_set_name (mWidget, "nsScrollbar");
gtk_signal_connect (GTK_OBJECT (mAdjustment),
"value_changed",
GTK_SIGNAL_FUNC (handle_scrollbar_value_changed),
this);
gtk_signal_connect (GTK_OBJECT (mAdjustment),
"destroy",
GTK_SIGNAL_FUNC (DestroySignal),
this);
return NS_OK;
}
void
nsScrollbar::OnDestroySignal(GtkWidget* aGtkWidget)
{
if ((void*)aGtkWidget == (void*)mAdjustment) {
mAdjustment = nsnull;
}
else {
nsWidget::OnDestroySignal(aGtkWidget);
}
}
//-------------------------------------------------------------------------
//
// Define the range settings
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetMaxRange (PRUint32 aEndRange)
{
if (mAdjustment) {
GTK_ADJUSTMENT (mAdjustment)->upper = (float) aEndRange;
gtk_signal_emit_by_name (GTK_OBJECT (mAdjustment), "changed");
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Return the range settings
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::GetMaxRange (PRUint32 & aMaxRange)
{
if (mAdjustment)
aMaxRange = (PRUint32) GTK_ADJUSTMENT (mAdjustment)->upper;
else
aMaxRange = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the thumb position
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetPosition (PRUint32 aPos)
{
// if (mAdjustment)
// gtk_adjustment_set_value (GTK_ADJUSTMENT (mAdjustment), (float) aPos);
if (mAdjustment && mWidget)
{
//
// The following bit of code borrowed from gtkrange.c,
// gtk_range_adjustment_value_changed():
//
// Ok, so, like, the problem is that the view manager expects
// SetPosition() to simply do that - set the position of the
// scroll bar. Nothing else!
//
// Unfortunately, calling gtk_adjustment_set_value() causes
// the adjustment object (mAdjustment) to emit a
// "value_changed" signal which in turn causes the
// scrollbar widget (mWidget) to scroll to the given position.
//
// The net result of this is that the content is scrolled
// twice, once by the view manager and once by the
// scrollbar - and things get messed up from then onwards.
//
// The following bit of code does the equivalent of
// gtk_adjustment_set_value(), except no signal is emitted.
//
GtkRange * range = GTK_RANGE(mWidget);
GtkAdjustment * adjustment = GTK_ADJUSTMENT(mAdjustment);
adjustment->value = (float) aPos;
if (range->old_value != adjustment->value)
{
gtk_range_slider_update (range);
gtk_range_clear_background (range);
range->old_value = adjustment->value;
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the current thumb position.
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::GetPosition (PRUint32 & aPos)
{
if (mAdjustment)
aPos = (PRUint32) GTK_ADJUSTMENT (mAdjustment)->value;
else
aPos = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the thumb size
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetThumbSize (PRUint32 aSize)
{
if (aSize > 0)
{
if (mAdjustment) {
GTK_ADJUSTMENT (mAdjustment)->page_increment = (float) aSize;
GTK_ADJUSTMENT (mAdjustment)->page_size = (float) aSize;
gtk_signal_emit_by_name (GTK_OBJECT (mAdjustment), "changed");
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the thumb size
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::GetThumbSize (PRUint32 & aThumbSize)
{
if (mAdjustment)
aThumbSize = (PRUint32) GTK_ADJUSTMENT (mAdjustment)->page_size;
else
aThumbSize = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set the line increment for this scrollbar
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetLineIncrement (PRUint32 aLineIncrement)
{
if (aLineIncrement > 0)
{
if (mAdjustment) {
GTK_ADJUSTMENT (mAdjustment)->step_increment = (float) aLineIncrement;
gtk_signal_emit_by_name (GTK_OBJECT (mAdjustment), "changed");
}
}
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Get the line increment for this scrollbar
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::GetLineIncrement (PRUint32 & aLineInc)
{
if (mAdjustment) {
aLineInc = (PRUint32) GTK_ADJUSTMENT (mAdjustment)->step_increment;
}
else
aLineInc = 0;
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Set all scrolling parameters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsScrollbar::SetParameters (PRUint32 aMaxRange, PRUint32 aThumbSize,
PRUint32 aPosition, PRUint32 aLineIncrement)
{
if (mAdjustment) {
int thumbSize = (((int) aThumbSize) > 0 ? aThumbSize : 1);
int maxRange = (((int) aMaxRange) > 0 ? aMaxRange : 10);
int mLineIncrement = (((int) aLineIncrement) > 0 ? aLineIncrement : 1);
int maxPos = maxRange - thumbSize;
int pos = ((int) aPosition) > maxPos ? maxPos - 1 : ((int) aPosition);
GTK_ADJUSTMENT (mAdjustment)->lower = 0;
GTK_ADJUSTMENT (mAdjustment)->upper = maxRange;
GTK_ADJUSTMENT (mAdjustment)->page_size = thumbSize;
GTK_ADJUSTMENT (mAdjustment)->page_increment = thumbSize;
GTK_ADJUSTMENT (mAdjustment)->step_increment = mLineIncrement;
// this will emit the changed signal for us
gtk_adjustment_set_value (GTK_ADJUSTMENT (mAdjustment), pos);
}
return NS_OK;
}
//-------------------------------------------------------------------------
int nsScrollbar::AdjustScrollBarPosition (int aPosition)
{
return 0; /* XXX */
}
//-------------------------------------------------------------------------
//
// Deal with scrollbar messages (actually implemented only in nsScrollbar)
//
//-------------------------------------------------------------------------
PRBool nsScrollbar::OnScroll (nsScrollbarEvent & aEvent, PRUint32 cPos)
{
PRBool result = PR_TRUE;
float newPosition;
switch (aEvent.message)
{
// scroll one line right or down
case NS_SCROLLBAR_LINE_NEXT:
{
newPosition = GTK_ADJUSTMENT (mAdjustment)->value;
// newPosition += mLineIncrement;
newPosition += 10;
PRUint32 thumbSize;
PRUint32 maxRange;
GetThumbSize (thumbSize);
GetMaxRange (maxRange);
PRUint32 max = maxRange - thumbSize;
if (newPosition > (int) max)
newPosition = (int) max;
// if an event callback is registered, give it the chance
// to change the increment
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
// scroll one line left or up
case NS_SCROLLBAR_LINE_PREV:
{
newPosition = GTK_ADJUSTMENT (mAdjustment)->value;
// newPosition -= mLineIncrement;
newPosition -= 10;
if (newPosition < 0)
newPosition = 0;
// if an event callback is registered, give it the chance
// to change the decrement
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
aEvent.widget = (nsWidget *) this;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
// Scrolls one page right or down
case NS_SCROLLBAR_PAGE_NEXT:
{
newPosition = GTK_ADJUSTMENT (mAdjustment)->value;
PRUint32 thumbSize;
GetThumbSize (thumbSize);
PRUint32 maxRange;
GetThumbSize (thumbSize);
GetMaxRange (maxRange);
PRUint32 max = maxRange - thumbSize;
if (newPosition > (int) max)
newPosition = (int) max;
// if an event callback is registered, give it the chance
// to change the increment
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
// Scrolls one page left or up.
case NS_SCROLLBAR_PAGE_PREV:
{
newPosition = GTK_ADJUSTMENT (mAdjustment)->value;
if (newPosition < 0)
newPosition = 0;
// if an event callback is registered, give it the chance
// to change the increment
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
// Scrolls to the absolute position. The current position is specified by
// the cPos parameter.
case NS_SCROLLBAR_POS:
{
newPosition = cPos;
// if an event callback is registered, give it the chance
// to change the increment
if (mEventCallback)
{
aEvent.position = (PRUint32) newPosition;
result = ConvertStatus ((*mEventCallback) (&aEvent));
newPosition = aEvent.position;
}
break;
}
}
/*
GTK_ADJUSTMENT(mAdjustment)->value = newPosition;
gtk_signal_emit_by_name(GTK_OBJECT(mAdjustment), "value_changed");
*/
/*
if (mEventCallback) {
aEvent.position = cPos;
result = ConvertStatus((*mEventCallback)(&aEvent));
newPosition = aEvent.position;
}
*/
return result;
}

View File

@@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsScrollbar_h__
#define nsScrollbar_h__
#include "nsWidget.h"
#include "nsIScrollbar.h"
/**
* Native GTK+ scrollbar wrapper.
*/
class nsScrollbar : public nsWidget,
public nsIScrollbar
{
public:
nsScrollbar(PRBool aIsVertical);
virtual ~nsScrollbar();
NS_DECL_ISUPPORTS_INHERITED
// nsIScrollBar implementation
NS_IMETHOD SetMaxRange(PRUint32 aEndRange);
NS_IMETHOD GetMaxRange(PRUint32& aMaxRange);
NS_IMETHOD SetPosition(PRUint32 aPos);
NS_IMETHOD GetPosition(PRUint32& aPos);
NS_IMETHOD SetThumbSize(PRUint32 aSize);
NS_IMETHOD GetThumbSize(PRUint32& aSize);
NS_IMETHOD SetLineIncrement(PRUint32 aSize);
NS_IMETHOD GetLineIncrement(PRUint32& aSize);
NS_IMETHOD SetParameters(PRUint32 aMaxRange, PRUint32 aThumbSize,
PRUint32 aPosition, PRUint32 aLineIncrement);
virtual PRBool OnScroll (nsScrollbarEvent & aEvent, PRUint32 cPos);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
private:
int mOrientation;
GtkAdjustment *mAdjustment;
int AdjustScrollBarPosition(int aPosition);
};
#endif /* nsScrollbar_h__ */

View File

@@ -0,0 +1,125 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nscore.h"
#include "nsIAllocator.h"
#include "plstr.h"
#include "stdio.h"
#include "prlink.h"
#include "nsSound.h"
#include <unistd.h>
#include <gtk/gtk.h>
/* used with esd_open_sound */
//static int esdref = -1;
static PRLibrary *lib = nsnull;
//typedef int (PR_CALLBACK *EsdOpenSoundType)(const char *host);
//typedef int (PR_CALLBACK *EsdCloseType)(int);
/* used to play the sounds from the find symbol call */
typedef int (PR_CALLBACK *EsdPlayFileType)(const char *, const char *, int);
NS_IMPL_ISUPPORTS1(nsSound, nsISound);
////////////////////////////////////////////////////////////////////////
nsSound::nsSound()
{
NS_INIT_REFCNT();
/* we don't need to do esd_open_sound if we are only going to play files
but we will if we want to do things like streams, etc
*/
// EsdOpenSoundType EsdOpenSound;
lib = PR_LoadLibrary("libesd.so");
/*
if (!lib)
return;
EsdOpenSound = (EsdOpenSoundType) PR_FindSymbol(lib, "esd_open_sound");
esdref = (*EsdOpenSound)("localhost");
*/
}
nsSound::~nsSound()
{
/* see above comment */
/*
if (esdref != -1)
{
EsdCloseType EsdClose = (EsdCloseType) PR_FindSymbol(lib, "esd_close");
(*EsdClose)(esdref);
esdref = -1;
}
*/
}
nsresult NS_NewSound(nsISound** aSound)
{
NS_PRECONDITION(aSound != nsnull, "null ptr");
if (! aSound)
return NS_ERROR_NULL_POINTER;
*aSound = new nsSound();
if (! *aSound)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aSound);
return NS_OK;
}
NS_METHOD nsSound::Init(void)
{
return NS_OK;
}
NS_METHOD nsSound::Beep()
{
::gdk_beep();
return NS_OK;
}
NS_METHOD nsSound::Play(nsIFileSpec *filespec)
{
if (lib)
{
char *filename;
filespec->GetNativePath(&filename);
g_print("there are some issues with playing sound right now, but this should work\n");
EsdPlayFileType EsdPlayFile = (EsdPlayFileType) PR_FindSymbol(lib, "esd_play_file");
(*EsdPlayFile)("mozilla", filename, 1);
nsCRT::free(filename);
return NS_OK;
}
return NS_OK;
}

View File

@@ -0,0 +1,41 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef __nsSound_h__
#define __nsSound_h__
#include "nsISound.h"
#include <gtk/gtk.h>
class nsSound : public nsISound {
public:
nsSound();
virtual ~nsSound();
NS_DECL_ISUPPORTS
NS_DECL_NSISOUND
};
#endif /* __nsSound_h__ */

View File

@@ -0,0 +1,97 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsTextAreaWidget.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsTextAreaWidget, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsTextAreaWidget, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsTextAreaWidget, nsITextAreaWidget, nsIWidget)
//-------------------------------------------------------------------------
//
// nsTextAreaWidget constructor
//
//-------------------------------------------------------------------------
nsTextAreaWidget::nsTextAreaWidget()
{
mBackground = NS_RGB(124, 124, 124);
}
//-------------------------------------------------------------------------
//
// nsTextAreaWidget destructor
//
//-------------------------------------------------------------------------
nsTextAreaWidget::~nsTextAreaWidget()
{
gtk_widget_destroy(mTextWidget);
mTextWidget = nsnull;
}
//-------------------------------------------------------------------------
//
// Create the native Text widget
//
//-------------------------------------------------------------------------
NS_METHOD nsTextAreaWidget::CreateNative(GtkObject *parentWindow)
{
PRBool oldIsReadOnly;
mWidget = gtk_scrolled_window_new(nsnull, nsnull);
gtk_container_set_border_width(GTK_CONTAINER(mWidget), 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(mWidget),
GTK_POLICY_NEVER,
GTK_POLICY_ALWAYS);
mTextWidget = gtk_text_new(nsnull, nsnull);
gtk_text_set_word_wrap(GTK_TEXT(mTextWidget), PR_TRUE);
gtk_widget_set_name(mTextWidget, "nsTextAreaWidget");
gtk_widget_show(mTextWidget);
SetPassword(mIsPassword);
SetReadOnly(mIsReadOnly, oldIsReadOnly);
gtk_container_add(GTK_CONTAINER(mWidget), mTextWidget);
return NS_OK;
}
//-------------------------------------------------------------------------
//
// set font for textarea
//
//-------------------------------------------------------------------------
/* virtual */
void nsTextAreaWidget::SetFontNative(GdkFont *aFont)
{
GtkStyle *style = gtk_style_copy(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0))->style);
// gtk_style_copy ups the ref count of the font
gdk_font_unref (style->font);
style->font = aFont;
gdk_font_ref(style->font);
gtk_widget_set_style(GTK_WIDGET (g_list_nth_data(gtk_container_children(GTK_CONTAINER (mWidget)),0)), style);
gtk_style_unref(style);
}

View File

@@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsTextAreaWidget_h__
#define nsTextAreaWidget_h__
#include "nsTextHelper.h"
#include "nsITextAreaWidget.h"
/**
* Native GTK+ multi-line edit control wrapper.
*/
class nsTextAreaWidget : public nsTextHelper
{
public:
nsTextAreaWidget();
virtual ~nsTextAreaWidget();
NS_DECL_ISUPPORTS_INHERITED
virtual void SetFontNative(GdkFont *aFont);
protected:
NS_METHOD CreateNative(GtkObject *parentWindow);
};
#endif // nsTextAreaWidget_h__

View File

@@ -0,0 +1,216 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsTextHelper.h"
#include "nsTextWidget.h"
#include "nsString.h"
NS_IMPL_ADDREF_INHERITED(nsTextHelper, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsTextHelper, nsWidget)
//-------------------------------------------------------------------------
//
// nsTextHelper constructor
//
//-------------------------------------------------------------------------
nsTextHelper::nsTextHelper() : nsWidget(), nsITextAreaWidget(), nsITextWidget()
{
mIsReadOnly = PR_FALSE;
mIsPassword = PR_FALSE;
}
//-------------------------------------------------------------------------
//
// nsTextHelper destructor
//
//-------------------------------------------------------------------------
nsTextHelper::~nsTextHelper()
{
}
//-------------------------------------------------------------------------
//
// Set initial parameters
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::PreCreateWidget(nsWidgetInitData *aInitData)
{
if (nsnull != aInitData) {
nsTextWidgetInitData* data = (nsTextWidgetInitData *) aInitData;
mIsPassword = data->mIsPassword;
mIsReadOnly = data->mIsReadOnly;
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetMaxTextLength(PRUint32 aChars)
{
// This is a normal entry only thing, not a text box
gtk_entry_set_max_length(GTK_ENTRY(mTextWidget), (int)aChars);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::GetText(nsString& aTextBuffer, PRUint32 aBufferSize, PRUint32& aActualSize)
{
char *str = nsnull;
if (GTK_IS_ENTRY(mTextWidget))
{
str = gtk_entry_get_text(GTK_ENTRY(mTextWidget));
}
else if (GTK_IS_TEXT(mTextWidget))
{
str = gtk_editable_get_chars (GTK_EDITABLE (mTextWidget), 0,
gtk_text_get_length (GTK_TEXT (mTextWidget)));
}
aTextBuffer.SetLength(0);
aTextBuffer.Append(str);
PRUint32 len = (PRUint32)strlen(str);
aActualSize = len;
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetText(const nsString& aText, PRUint32& aActualSize)
{
if (GTK_IS_ENTRY(mTextWidget)) {
gtk_entry_set_text(GTK_ENTRY(mTextWidget),
(const gchar *)nsAutoCString(aText));
} else if (GTK_IS_TEXT(mTextWidget)) {
gtk_editable_delete_text(GTK_EDITABLE(mTextWidget), 0,
gtk_text_get_length(GTK_TEXT (mTextWidget)));
gtk_text_insert(GTK_TEXT(mTextWidget),
nsnull, nsnull, nsnull,
(const char *)nsAutoCString(aText),
aText.Length());
}
aActualSize = aText.Length();
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::InsertText(const nsString &aText,
PRUint32 aStartPos,
PRUint32 aEndPos,
PRUint32& aActualSize)
{
gtk_editable_insert_text(GTK_EDITABLE(mTextWidget),
(const gchar *)nsAutoCString(aText),
(gint)aText.Length(), (gint*)&aStartPos);
aActualSize = aText.Length();
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::RemoveText()
{
if (GTK_IS_ENTRY(mTextWidget)) {
gtk_entry_set_text(GTK_ENTRY(mTextWidget), "");
} else if (GTK_IS_TEXT(mTextWidget)) {
gtk_editable_delete_text(GTK_EDITABLE(mTextWidget), 0,
gtk_text_get_length(GTK_TEXT (mTextWidget)));
}
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetPassword(PRBool aIsPassword)
{
mIsPassword = aIsPassword?PR_FALSE:PR_TRUE;
if (GTK_IS_ENTRY(mTextWidget)) {
gtk_entry_set_visibility(GTK_ENTRY(mTextWidget), mIsPassword);
}
// this won't work for gtk_texts
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetReadOnly(PRBool aReadOnlyFlag, PRBool& aOldReadOnlyFlag)
{
NS_ASSERTION(nsnull != mTextWidget,
"SetReadOnly - Widget is NULL, Create may not have been called!");
aOldReadOnlyFlag = mIsReadOnly;
mIsReadOnly = aReadOnlyFlag?PR_FALSE:PR_TRUE;
gtk_editable_set_editable(GTK_EDITABLE(mTextWidget), mIsReadOnly);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SelectAll()
{
nsString text;
PRUint32 actualSize = 0;
PRUint32 numChars = GetText(text, 0, actualSize);
SetSelection(0, numChars);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetSelection(PRUint32 aStartSel, PRUint32 aEndSel)
{
gtk_editable_select_region(GTK_EDITABLE(mTextWidget), aStartSel, aEndSel);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::GetSelection(PRUint32 *aStartSel, PRUint32 *aEndSel)
{
#if 0
XmTextPosition left;
XmTextPosition right;
if (XmTextGetSelectionPosition(mTextWidget, &left, &right)) {
*aStartSel = (PRUint32)left;
*aEndSel = (PRUint32)right;
} else {
printf("nsTextHelper::GetSelection Error getting positions\n");
return NS_ERROR_FAILURE;
}
#endif
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::SetCaretPosition(PRUint32 aPosition)
{
gtk_editable_set_position(GTK_EDITABLE(mTextWidget), aPosition);
return NS_OK;
}
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextHelper::GetCaretPosition(PRUint32& aPosition)
{
aPosition = (PRUint32)GTK_EDITABLE(mTextWidget)->current_pos;
return NS_OK;
}

View File

@@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsTextHelper_h__
#define nsTextHelper_h__
#include "nsITextWidget.h"
#include "nsITextAreaWidget.h"
#include "nsWidget.h"
/**
* Base class for nsTextAreaWidget and nsTextWidget
*/
class nsTextHelper : public nsWidget,
public nsITextAreaWidget,
public nsITextWidget
{
public:
nsTextHelper();
virtual ~nsTextHelper();
// nsISupports
NS_IMETHOD_(nsrefcnt) AddRef();
NS_IMETHOD_(nsrefcnt) Release();
NS_IMETHOD SelectAll();
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aInitData);
NS_IMETHOD SetMaxTextLength(PRUint32 aChars);
NS_IMETHOD GetText(nsString& aTextBuffer, PRUint32 aBufferSize, PRUint32& aActualSize);
NS_IMETHOD SetText(const nsString &aText, PRUint32& aActualSize);
NS_IMETHOD InsertText(const nsString &aText, PRUint32 aStartPos, PRUint32 aEndPos, PRUint32& aActualSize);
NS_IMETHOD RemoveText();
NS_IMETHOD SetPassword(PRBool aIsPassword);
NS_IMETHOD SetReadOnly(PRBool aNewReadOnlyFlag, PRBool& aOldReadOnlyFlag);
NS_IMETHOD SetSelection(PRUint32 aStartSel, PRUint32 aEndSel);
NS_IMETHOD GetSelection(PRUint32 *aStartSel, PRUint32 *aEndSel);
NS_IMETHOD SetCaretPosition(PRUint32 aPosition);
NS_IMETHOD GetCaretPosition(PRUint32& aPosition);
protected:
GtkWidget *mTextWidget;
PRBool mIsPassword;
PRBool mIsReadOnly;
};
#endif // nsTextHelper_h__

View File

@@ -0,0 +1,130 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include <gtk/gtk.h>
#include "nsTextWidget.h"
#include "nsString.h"
#include "nsGtkEventHandler.h"
extern int mIsPasswordCallBacksInstalled;
NS_IMPL_ADDREF_INHERITED(nsTextWidget, nsWidget)
NS_IMPL_RELEASE_INHERITED(nsTextWidget, nsWidget)
NS_IMPL_QUERY_INTERFACE2(nsTextWidget, nsITextWidget, nsIWidget)
//-------------------------------------------------------------------------
//
// nsTextWidget constructor
//
//-------------------------------------------------------------------------
nsTextWidget::nsTextWidget() : nsTextHelper()
{
}
//-------------------------------------------------------------------------
//
// nsTextWidget destructor
//
//-------------------------------------------------------------------------
nsTextWidget::~nsTextWidget()
{
// avoid freeing this twice in other destructors
mTextWidget = nsnull;
}
//-------------------------------------------------------------------------
//
// Create the native Entry widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsTextWidget::CreateNative(GtkObject *parentWindow)
{
PRBool oldIsReadOnly;
mWidget = gtk_entry_new();
#ifdef USE_SUPERWIN
if (!GDK_IS_SUPERWIN(parentWindow)) {
g_print("Damn, brother. That's not a superwin.\n");
return NS_ERROR_FAILURE;
}
GdkSuperWin *superwin = GDK_SUPERWIN(parentWindow);
mMozBox = gtk_mozbox_new(superwin->bin_window);
#endif /* USE_SUPERWIN */
// used by nsTextHelper because nsTextArea needs a scrolled_window
mTextWidget = mWidget;
gtk_widget_set_name(mWidget, "nsTextWidget");
/*
* GTK's text widget does XIM for us, so we don't want to use the default key handler
* which does XIM, so we connect to a non-XIM key event for the text widget
*/
gtk_signal_connect_after(GTK_OBJECT(mWidget),
"key_press_event",
GTK_SIGNAL_FUNC(handle_key_press_event_for_text),
this);
gtk_signal_connect(GTK_OBJECT(mWidget),
"key_release_event",
GTK_SIGNAL_FUNC(handle_key_release_event_for_text),
this);
SetPassword(mIsPassword);
SetReadOnly(mIsReadOnly, oldIsReadOnly);
gtk_widget_show(mWidget);
// These are needed so that the events will go to us and not our parent.
AddToEventMask(mWidget,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_EXPOSURE_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
#ifdef USE_SUPERWIN
// make sure that we put the scrollbar into the mozbox
gtk_container_add(GTK_CONTAINER(mMozBox), mWidget);
#endif /* USE_SUPERWIN */
return NS_OK;
}
PRBool nsTextWidget::OnKey(nsKeyEvent &aEvent)
{
if (mEventCallback) {
return DispatchWindowEvent(&aEvent);
}
return PR_FALSE;
}

View File

@@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsTextWidget_h__
#define nsTextWidget_h__
#include "nsTextHelper.h"
#include "nsITextWidget.h"
/**
* Native GTK+ single line edit control wrapper.
*/
class nsTextWidget : public nsTextHelper
{
public:
nsTextWidget();
virtual ~nsTextWidget();
NS_DECL_ISUPPORTS_INHERITED
PRBool OnKey(nsKeyEvent &aEvent);
protected:
NS_IMETHOD CreateNative(GtkObject *parentWindow);
};
#endif // nsTextWidget_h__

View File

@@ -0,0 +1,144 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nscore.h" // needed for 'nsnull'
#include "nsToolkit.h"
//
// Static thread local storage index of the Toolkit
// object associated with a given thread...
//
static PRUintn gToolkitTLSIndex = 0;
//-------------------------------------------------------------------------
//
// constructor
//
//-------------------------------------------------------------------------
nsToolkit::nsToolkit()
{
NS_INIT_REFCNT();
mSharedGC = nsnull;
}
//-------------------------------------------------------------------------
//
// destructor
//
//-------------------------------------------------------------------------
nsToolkit::~nsToolkit()
{
if (mSharedGC)
gdk_gc_unref(mSharedGC);
// Remove the TLS reference to the toolkit...
PR_SetThreadPrivate(gToolkitTLSIndex, nsnull);
}
//-------------------------------------------------------------------------
//
// nsISupports implementation macro
//
//-------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(nsToolkit, nsIToolkit)
void nsToolkit::CreateSharedGC(void)
{
GdkPixmap *pixmap;
if (mSharedGC)
return;
pixmap = ::gdk_pixmap_new (NULL, 1, 1, gdk_rgb_get_visual()->depth);
mSharedGC = ::gdk_gc_new (pixmap);
gdk_pixmap_unref (pixmap);
mSharedGC = gdk_gc_ref(mSharedGC);
}
GdkGC *nsToolkit::GetSharedGC(void)
{
return gdk_gc_ref(mSharedGC);
}
//-------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsToolkit::Init(PRThread *aThread)
{
CreateSharedGC();
return NS_OK;
}
//-------------------------------------------------------------------------
//
// Return the nsIToolkit for the current thread. If a toolkit does not
// yet exist, then one will be created...
//
//-------------------------------------------------------------------------
NS_METHOD NS_GetCurrentToolkit(nsIToolkit* *aResult)
{
nsIToolkit* toolkit = nsnull;
nsresult rv = NS_OK;
PRStatus status;
// Create the TLS index the first time through...
if (0 == gToolkitTLSIndex) {
status = PR_NewThreadPrivateIndex(&gToolkitTLSIndex, NULL);
if (PR_FAILURE == status) {
rv = NS_ERROR_FAILURE;
}
}
if (NS_SUCCEEDED(rv)) {
toolkit = (nsIToolkit*)PR_GetThreadPrivate(gToolkitTLSIndex);
//
// Create a new toolkit for this thread...
//
if (!toolkit) {
toolkit = new nsToolkit();
if (!toolkit) {
rv = NS_ERROR_OUT_OF_MEMORY;
} else {
NS_ADDREF(toolkit);
toolkit->Init(PR_GetCurrentThread());
//
// The reference stored in the TLS is weak. It is removed in the
// nsToolkit destructor...
//
PR_SetThreadPrivate(gToolkitTLSIndex, (void*)toolkit);
}
} else {
NS_ADDREF(toolkit);
}
*aResult = toolkit;
}
return rv;
}

View File

@@ -0,0 +1,55 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef TOOLKIT_H
#define TOOLKIT_H
#include "nsIToolkit.h"
#include <gtk/gtk.h>
/**
* Wrapper around the thread running the message pump.
* The toolkit abstraction is necessary because the message pump must
* execute within the same thread that created the widget under Win32.
*/
class nsToolkit : public nsIToolkit
{
public:
nsToolkit();
virtual ~nsToolkit();
NS_DECL_ISUPPORTS
NS_IMETHOD Init(PRThread *aThread);
void CreateSharedGC(void);
GdkGC *GetSharedGC(void);
private:
GdkGC *mSharedGC;
};
#endif // TOOLKIT_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,410 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsWidget_h__
#define nsWidget_h__
#include "nsBaseWidget.h"
#include "nsIRegion.h"
// XXX: This must go away when nsAutoCString moves out of nsFileSpec.h
#include "nsFileSpec.h" // for nsAutoCString()
class nsILookAndFeel;
class nsIAppShell;
class nsIToolkit;
#include <gtk/gtk.h>
#include <gdk/gdkprivate.h>
#include "gtkmozbox.h"
#define USE_SUPERWIN
#define NSRECT_TO_GDKRECT(ns,gdk) \
PR_BEGIN_MACRO \
gdk.x = ns.x; \
gdk.y = ns.y; \
gdk.width = ns.width; \
gdk.height = ns.height; \
PR_END_MACRO
#define NSCOLOR_TO_GDKCOLOR(n,g) \
PR_BEGIN_MACRO \
g.red = 256 * NS_GET_R(n); \
g.green = 256 * NS_GET_G(n); \
g.blue = 256 * NS_GET_B(n); \
PR_END_MACRO
#define NS_TO_GDK_RGB(ns) (ns & 0xff) << 16 | (ns & 0xff00) | ((ns >> 16) & 0xff)
/**
* Base of all GTK+ native widgets.
*/
class nsWidget : public nsBaseWidget
{
public:
nsWidget();
virtual ~nsWidget();
NS_IMETHOD Create(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull);
NS_IMETHOD Create(nsNativeWidget aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell = nsnull,
nsIToolkit *aToolkit = nsnull,
nsWidgetInitData *aInitData = nsnull);
NS_IMETHOD Destroy(void);
nsIWidget* GetParent(void);
NS_IMETHOD SetModal(PRBool aModal);
NS_IMETHOD Show(PRBool state);
NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent);
NS_IMETHOD IsVisible(PRBool &aState);
NS_IMETHOD Move(PRInt32 aX, PRInt32 aY);
NS_IMETHOD Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth,
PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Enable(PRBool aState);
NS_IMETHOD SetFocus(void);
PRBool OnResize(nsSizeEvent event);
virtual PRBool OnResize(nsRect &aRect);
virtual PRBool OnMove(PRInt32 aX, PRInt32 aY);
nsIFontMetrics *GetFont(void);
NS_IMETHOD SetFont(const nsFont &aFont);
NS_IMETHOD SetBackgroundColor(const nscolor &aColor);
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD SetColorMap(nsColorMap *aColorMap);
void* GetNativeData(PRUint32 aDataType);
NS_IMETHOD GetAbsoluteBounds(nsRect &aRect);
NS_IMETHOD WidgetToScreen(const nsRect &aOldRect, nsRect &aNewRect);
NS_IMETHOD ScreenToWidget(const nsRect &aOldRect, nsRect &aNewRect);
NS_IMETHOD BeginResizingChildren(void);
NS_IMETHOD EndResizingChildren(void);
NS_IMETHOD GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight);
NS_IMETHOD SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight);
// Use this to set the name of a widget for normal widgets.. not the same as the nsWindow version
NS_IMETHOD SetTitle(const nsString& aTitle);
virtual void ConvertToDeviceCoordinates(nscoord &aX, nscoord &aY);
// the following are nsWindow specific, and just stubbed here
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect) { return NS_ERROR_FAILURE; }
NS_IMETHOD SetMenuBar(nsIMenuBar *aMenuBar) { return NS_ERROR_FAILURE; }
NS_IMETHOD ShowMenuBar(PRBool aShow) { return NS_ERROR_FAILURE; }
// *could* be done on a widget, but that would be silly wouldn't it?
NS_IMETHOD CaptureMouse(PRBool aCapture) { return NS_ERROR_FAILURE; }
NS_IMETHOD Invalidate(PRBool aIsSynchronous);
NS_IMETHOD Invalidate(const nsRect &aRect, PRBool aIsSynchronous);
NS_IMETHOD InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous);
NS_IMETHOD Update(void);
NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus);
void InitEvent(nsGUIEvent& event, PRUint32 aEventType, nsPoint* aPoint = nsnull);
// Utility functions
void HandleEvent(GdkEvent *event);
PRBool ConvertStatus(nsEventStatus aStatus);
PRBool DispatchMouseEvent(nsMouseEvent& aEvent);
PRBool DispatchStandardEvent(PRUint32 aMsg);
PRBool DispatchFocus(nsGUIEvent &aEvent);
// are we a "top level" widget?
PRBool mIsToplevel;
#ifdef DEBUG
void IndentByDepth(FILE* out);
#endif
// Return the Gdk window used for rendering
virtual GdkWindow * GetRenderWindow(GtkObject * aGtkWidget);
protected:
virtual void InitCallbacks(char * aName = nsnull);
virtual void OnDestroy();
NS_IMETHOD CreateNative(GtkObject *parentWindow) { return NS_OK; }
nsresult CreateWidget(nsIWidget *aParent,
const nsRect &aRect,
EVENT_CALLBACK aHandleEventFunction,
nsIDeviceContext *aContext,
nsIAppShell *aAppShell,
nsIToolkit *aToolkit,
nsWidgetInitData *aInitData,
nsNativeWidget aNativeParent = nsnull);
PRBool DispatchWindowEvent(nsGUIEvent* event);
// Return the Gdk window whose background should change
virtual GdkWindow *GetWindowForSetBackground();
// Sets font for widgets
virtual void SetFontNative(GdkFont *aFont);
// Sets backround for widgets
virtual void SetBackgroundColorNative(GdkColor *aColorNor,
GdkColor *aColorBri,
GdkColor *aColorDark);
//////////////////////////////////////////////////////////////////
//
// GTK signal installers
//
//////////////////////////////////////////////////////////////////
void InstallMotionNotifySignal(GtkWidget * aWidget);
void InstallDragMotionSignal(GtkWidget * aWidget);
void InstallDragLeaveSignal(GtkWidget * aWidget);
void InstallDragBeginSignal(GtkWidget * aWidget);
void InstallDragDropSignal(GtkWidget * aWidget);
void InstallEnterNotifySignal(GtkWidget * aWidget);
void InstallLeaveNotifySignal(GtkWidget * aWidget);
void InstallButtonPressSignal(GtkWidget * aWidget);
void InstallButtonReleaseSignal(GtkWidget * aWidget);
virtual
void InstallFocusInSignal(GtkWidget * aWidget);
virtual
void InstallFocusOutSignal(GtkWidget * aWidget);
void InstallRealizeSignal(GtkWidget * aWidget);
void AddToEventMask(GtkWidget * aWidget,
gint aEventMask);
//////////////////////////////////////////////////////////////////
//
// OnSomething handlers
//
//////////////////////////////////////////////////////////////////
virtual void OnMotionNotifySignal(GdkEventMotion * aGdkMotionEvent);
virtual void OnDragMotionSignal(GdkDragContext *aGdkDragContext,
gint x,
gint y,
guint time);
/* OnDragEnterSignal is not a real signal.. it is only called from OnDragMotionSignal */
virtual void OnDragEnterSignal(GdkDragContext *aGdkDragContext,
gint x,
gint y,
guint time);
virtual void OnDragLeaveSignal(GdkDragContext *context,
guint time);
virtual void OnDragBeginSignal(GdkDragContext *aGdkDragContext);
virtual void OnDragDropSignal(GdkDragContext *aGdkDragContext,
gint x,
gint y,
guint time);
virtual void OnEnterNotifySignal(GdkEventCrossing * aGdkCrossingEvent);
virtual void OnLeaveNotifySignal(GdkEventCrossing * aGdkCrossingEvent);
virtual void OnButtonPressSignal(GdkEventButton * aGdkButtonEvent);
virtual void OnButtonReleaseSignal(GdkEventButton * aGdkButtonEvent);
virtual void OnFocusInSignal(GdkEventFocus * aGdkFocusEvent);
virtual void OnFocusOutSignal(GdkEventFocus * aGdkFocusEvent);
virtual void OnRealize(GtkWidget *aWidget);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
// Static method used to trampoline to OnDestroySignal
static gint DestroySignal(GtkWidget * aGtkWidget,
nsWidget* aWidget);
static void SuppressModality(PRBool aSuppress);
public:
PRBool mIMEEnable;
PRUnichar* mIMECompositionUniString;
PRInt32 mIMECompositionUniStringSize;
void SetXICSpotLocation(nsPoint aPoint);
protected:
//////////////////////////////////////////////////////////////////
//
// GTK widget signals
//
//////////////////////////////////////////////////////////////////
static gint MotionNotifySignal(GtkWidget * aWidget,
GdkEventMotion * aGdkMotionEvent,
gpointer aData);
static gint DragMotionSignal(GtkWidget * aWidget,
GdkDragContext *context,
gint x,
gint y,
guint time,
void *data);
static void DragLeaveSignal(GtkWidget * aWidget,
GdkDragContext *aDragContext,
guint time,
void *aData);
static gint DragBeginSignal(GtkWidget * aWidget,
GdkDragContext *context,
gint x,
gint y,
guint time,
void *data);
static gint DragDropSignal(GtkWidget * aWidget,
GdkDragContext *context,
gint x,
gint y,
guint time,
void *data);
static gint EnterNotifySignal(GtkWidget * aWidget,
GdkEventCrossing * aGdkCrossingEvent,
gpointer aData);
static gint LeaveNotifySignal(GtkWidget * aWidget,
GdkEventCrossing * aGdkCrossingEvent,
gpointer aData);
static gint ButtonPressSignal(GtkWidget * aWidget,
GdkEventButton * aGdkButtonEvent,
gpointer aData);
static gint ButtonReleaseSignal(GtkWidget * aWidget,
GdkEventButton * aGdkButtonEvent,
gpointer aData);
static gint RealizeSignal(GtkWidget * aWidget,
gpointer aData);
static gint FocusInSignal(GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
gpointer aData);
static gint FocusOutSignal(GtkWidget * aWidget,
GdkEventFocus * aGdkFocusEvent,
gpointer aData);
protected:
//////////////////////////////////////////////////////////////////
//
// GTK event support methods
//
//////////////////////////////////////////////////////////////////
void InstallSignal(GtkWidget * aWidget,
gchar * aSignalName,
GtkSignalFunc aSignalFunction);
PRBool DropEvent(GtkWidget * aWidget,
GdkWindow * aEventWindow);
void InitMouseEvent(GdkEventButton * aGdkButtonEvent,
nsMouseEvent & anEvent,
PRUint32 aEventType);
#ifdef DEBUG
nsCAutoString debug_GetName(GtkObject * aGtkWidget);
nsCAutoString debug_GetName(GtkWidget * aGtkWidget);
PRInt32 debug_GetRenderXID(GtkObject * aGtkWidget);
PRInt32 debug_GetRenderXID(GtkWidget * aGtkWidget);
#endif
guint32 mGrabTime;
GtkWidget *mWidget;
// our mozbox for those native widgets
GtkWidget *mMozBox;
nsIWidget *mParent;
// This is the composite update area (union of all the calls to
// Invalidate)
nsIRegion *mUpdateArea;
PRBool mShown;
PRUint32 mPreferredWidth, mPreferredHeight;
PRBool mListenForResizes;
GdkICPrivate *mIC;
GdkICPrivate *GetXIC();
void SetXIC(GdkICPrivate *aIC);
void GetXYFromPosition(unsigned long *aX, unsigned long *aY);
// this is the rollup listener variables
static nsIRollupListener *gRollupListener;
static nsIWidget *gRollupWidget;
static PRBool gRollupConsumeRollupEvent;
private:
PRBool mIsDragDest;
static nsILookAndFeel *sLookAndFeel;
static PRUint32 sWidgetCount;
//
// Keep track of the last widget being "dragged"
//
static nsWidget *sButtonMotionTarget;
static gint sButtonMotionRootX;
static gint sButtonMotionRootY;
static gint sButtonMotionWidgetX;
static gint sButtonMotionWidgetY;
};
#endif /* nsWidget_h__ */

View File

@@ -0,0 +1,274 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsIFactory.h"
#include "nsISupports.h"
#include "nsIButton.h"
#include "nsITextWidget.h"
#include "nsWidgetsCID.h"
#include "nsToolkit.h"
#include "nsWindow.h"
#include "nsAppShell.h"
#include "nsButton.h"
#include "nsScrollbar.h"
#include "nsCheckButton.h"
#include "nsRadioButton.h"
#include "nsTextWidget.h"
#include "nsTextAreaWidget.h"
#include "nsFileWidget.h"
#include "nsFileSpecWithUIImpl.h"
#include "nsListBox.h"
#include "nsComboBox.h"
#include "nsLookAndFeel.h"
#include "nsLabel.h"
#ifdef LOSER
#include "nsMenuBar.h"
#include "nsMenu.h"
#include "nsMenuItem.h"
#include "nsPopUpMenu.h"
#include "nsContextMenu.h"
#endif
#include "nsFontRetrieverService.h"
// Drag & Drop, Clipboard
#include "nsClipboard.h"
#include "nsTransferable.h"
#include "nsXIFFormatConverter.h"
#include "nsDragService.h"
#include "nsSound.h"
static NS_DEFINE_IID(kCWindow, NS_WINDOW_CID);
static NS_DEFINE_IID(kCChild, NS_CHILD_CID);
static NS_DEFINE_IID(kCButton, NS_BUTTON_CID);
static NS_DEFINE_IID(kCCheckButton, NS_CHECKBUTTON_CID);
static NS_DEFINE_IID(kCCombobox, NS_COMBOBOX_CID);
static NS_DEFINE_IID(kCFileOpen, NS_FILEWIDGET_CID);
static NS_DEFINE_IID(kCListbox, NS_LISTBOX_CID);
static NS_DEFINE_IID(kCRadioButton, NS_RADIOBUTTON_CID);
static NS_DEFINE_IID(kCHorzScrollbar, NS_HORZSCROLLBAR_CID);
static NS_DEFINE_IID(kCVertScrollbar, NS_VERTSCROLLBAR_CID);
static NS_DEFINE_IID(kCTextArea, NS_TEXTAREA_CID);
static NS_DEFINE_IID(kCTextField, NS_TEXTFIELD_CID);
static NS_DEFINE_IID(kCAppShell, NS_APPSHELL_CID);
static NS_DEFINE_IID(kCToolkit, NS_TOOLKIT_CID);
static NS_DEFINE_IID(kCLookAndFeel, NS_LOOKANDFEEL_CID);
static NS_DEFINE_IID(kCLabel, NS_LABEL_CID);
#if 0
static NS_DEFINE_IID(kCMenuBar, NS_MENUBAR_CID);
static NS_DEFINE_IID(kCMenu, NS_MENU_CID);
static NS_DEFINE_IID(kCMenuItem, NS_MENUITEM_CID);
static NS_DEFINE_IID(kCPopUpMenu, NS_POPUPMENU_CID);
static NS_DEFINE_IID(kCContextMenu, NS_CONTEXTMENU_CID);
#endif
static NS_DEFINE_IID(kCFontRetrieverService, NS_FONTRETRIEVERSERVICE_CID);
// Drag & Drop, Clipboard
static NS_DEFINE_IID(kCDataObj, NS_DATAOBJ_CID);
static NS_DEFINE_IID(kCClipboard, NS_CLIPBOARD_CID);
static NS_DEFINE_IID(kCTransferable, NS_TRANSFERABLE_CID);
static NS_DEFINE_IID(kCDataFlavor, NS_DATAFLAVOR_CID);
static NS_DEFINE_IID(kCXIFFormatConverter, NS_XIFFORMATCONVERTER_CID);
static NS_DEFINE_IID(kCDragService, NS_DRAGSERVICE_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
// Sound services (just Beep for now)
static NS_DEFINE_CID(kCSound, NS_SOUND_CID);
static NS_DEFINE_CID(kCFileSpecWithUI, NS_FILESPECWITHUI_CID);
class nsWidgetFactory : public nsIFactory
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIFACTORY
nsWidgetFactory(const nsCID &aClass);
virtual ~nsWidgetFactory();
private:
nsCID mClassID;
};
nsWidgetFactory::nsWidgetFactory(const nsCID &aClass)
{
NS_INIT_ISUPPORTS();
mClassID = aClass;
}
nsWidgetFactory::~nsWidgetFactory()
{
}
NS_IMPL_ISUPPORTS(nsWidgetFactory, NS_GET_IID(nsIFactory))
nsresult nsWidgetFactory::CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult)
{
if (aResult == NULL) {
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
if (nsnull != aOuter)
return NS_ERROR_NO_AGGREGATION;
nsISupports *inst = nsnull;
if (mClassID.Equals(kCWindow)) {
inst = (nsISupports *)new nsWindow();
}
else if (mClassID.Equals(kCChild)) {
inst = (nsISupports *)new ChildWindow();
}
else if (mClassID.Equals(kCButton)) {
inst = (nsISupports*)(nsWidget *)new nsButton();
}
else if (mClassID.Equals(kCCheckButton)) {
inst = (nsISupports*)(nsWidget *)new nsCheckButton();
}
else if (mClassID.Equals(kCCombobox)) {
inst = (nsISupports*)(nsWidget *)new nsComboBox();
}
else if (mClassID.Equals(kCRadioButton)) {
inst = (nsISupports*)(nsWidget *)new nsRadioButton();
}
else if (mClassID.Equals(kCFileOpen)) {
inst = (nsISupports*)new nsFileWidget();
}
else if (mClassID.Equals(kCListbox)) {
inst = (nsISupports*)(nsWidget *)new nsListBox();
}
else if (mClassID.Equals(kCHorzScrollbar)) {
inst = (nsISupports*)(nsWidget *)new nsScrollbar(PR_FALSE);
}
else if (mClassID.Equals(kCVertScrollbar)) {
inst = (nsISupports*)(nsWidget *)new nsScrollbar(PR_TRUE);
}
else if (mClassID.Equals(kCTextArea)) {
inst = (nsISupports*)(nsWidget *)new nsTextAreaWidget();
}
else if (mClassID.Equals(kCTextField)) {
inst = (nsISupports*)(nsWidget *)new nsTextWidget();
}
else if (mClassID.Equals(kCAppShell)) {
inst = (nsISupports*)new nsAppShell();
}
else if (mClassID.Equals(kCToolkit)) {
inst = (nsISupports*)(nsWidget *)new nsToolkit();
}
else if (mClassID.Equals(kCLookAndFeel)) {
inst = (nsISupports*)(nsWidget *)new nsLookAndFeel();
}
else if (mClassID.Equals(kCLabel)) {
inst = (nsISupports*)(nsWidget *)new nsLabel();
}
#if 0
else if (mClassID.Equals(kCMenuBar)) {
inst = (nsISupports*)(nsIMenuBar *)new nsMenuBar();
}
else if (mClassID.Equals(kCMenu)) {
inst = (nsISupports*)(nsIMenu *)new nsMenu();
}
else if (mClassID.Equals(kCMenuItem)) {
inst = (nsISupports*)(nsIMenuItem *)new nsMenuItem();
}
else if (mClassID.Equals(kCPopUpMenu)) {
inst = (nsISupports*)new nsPopUpMenu();
}
/*
else if (mClassID.Equals(kCContextMenu)) {
inst = (nsISupports*)(nsIContextMenu*)new nsContextMenu();
}
*/
#endif
else if (mClassID.Equals(kCSound)) {
nsISound* aSound = nsnull;
NS_NewSound(&aSound);
inst = (nsISupports*) aSound;
}
else if (mClassID.Equals(kCTransferable)) {
inst = (nsISupports*)new nsTransferable();
}
else if (mClassID.Equals(kCClipboard)) {
inst = (nsISupports*)new nsClipboard();
}
else if (mClassID.Equals(kCXIFFormatConverter))
inst = (nsISupports*)new nsXIFFormatConverter();
else if (mClassID.Equals(kCFontRetrieverService))
inst = (nsISupports*)(nsIFontRetrieverService *) new nsFontRetrieverService();
else if (mClassID.Equals(kCDragService))
inst = (nsISupports*) (nsIDragService *) new nsDragService();
else if (mClassID.Equals(kCFileSpecWithUI))
inst = (nsISupports*) (nsIFileSpecWithUI *) new nsFileSpecWithUIImpl;
else {
printf("nsWidgetFactory::CreateInstance(), unhandled class.\n");
}
if (inst == NULL) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(inst);
nsresult res = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return res;
}
nsresult nsWidgetFactory::LockFactory(PRBool aLock)
{
// Not implemented in simplest case.
return NS_OK;
}
// return the proper factory to the caller
extern "C" NS_WIDGET nsresult
NSGetFactory(nsISupports* serviceMgr,
const nsCID &aClass,
const char *aClassName,
const char *aProgID,
nsIFactory **aFactory)
{
if (nsnull == aFactory) {
return NS_ERROR_NULL_POINTER;
}
*aFactory = new nsWidgetFactory(aClass);
if (nsnull == aFactory) {
return NS_ERROR_OUT_OF_MEMORY;
}
return (*aFactory)->QueryInterface(kIFactoryIID, (void**)aFactory);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsWindow_h__
#define nsWindow_h__
#include "nsISupports.h"
#include "nsWidget.h"
#include "nsString.h"
#include "gtkmozarea.h"
#include "gdksuperwin.h"
class nsFont;
class nsIAppShell;
/**
* Native GTK++ window wrapper.
*/
class nsWindow : public nsWidget
{
public:
// nsIWidget interface
nsWindow();
virtual ~nsWindow();
NS_IMETHOD WidgetToScreen(const nsRect &aOldRect, nsRect &aNewRect);
NS_IMETHOD PreCreateWidget(nsWidgetInitData *aWidgetInitData);
virtual void* GetNativeData(PRUint32 aDataType);
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect);
NS_IMETHOD ScrollRect(nsRect &aSrcRect, PRInt32 aDx, PRInt32 aDy);
NS_IMETHOD SetTitle(const nsString& aTitle);
NS_IMETHOD Show(PRBool aShow);
NS_IMETHOD CaptureMouse(PRBool aCapture);
NS_IMETHOD Move(PRInt32 aX, PRInt32 aY);
NS_IMETHOD Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth,
PRInt32 aHeight, PRBool aRepaint);
NS_IMETHOD BeginResizingChildren(void);
NS_IMETHOD EndResizingChildren(void);
NS_IMETHOD Destroy(void);
#ifdef USE_SUPERWIN
NS_IMETHOD GetAbsoluteBounds(nsRect &aRect);
NS_IMETHOD CaptureRollupEvents(nsIRollupListener * aListener,
PRBool aDoCapture,
PRBool aConsumeRollupEvent);
NS_IMETHOD Invalidate(PRBool aIsSynchronous);
NS_IMETHOD Invalidate(const nsRect &aRect, PRBool aIsSynchronous);
NS_IMETHOD SetBackgroundColor(const nscolor &aColor);
NS_IMETHOD SetCursor(nsCursor aCursor);
NS_IMETHOD SetFocus(void);
void QueueDraw();
void UnqueueDraw();
void DoPaint(PRInt32 x, PRInt32 y, PRInt32 width, PRInt32 height,
nsIRegion *aClipRegion);
static gboolean UpdateIdle (gpointer data);
NS_IMETHOD Update(void);
virtual void OnFocusInSignal(GdkEventFocus * aGdkFocusEvent);
virtual void OnFocusOutSignal(GdkEventFocus * aGdkFocusEvent);
virtual void InstallFocusInSignal(GtkWidget * aWidget);
virtual void InstallFocusOutSignal(GtkWidget * aWidget);
#endif /* USE_SUPERWIN */
gint ConvertBorderStyles(nsBorderStyle bs);
// Add an XATOM property to this window.
void StoreProperty(char *property, unsigned char *data);
virtual PRBool IsChild() const;
void SetIsDestroying(PRBool val) {
mIsDestroyingWindow = val;
}
PRBool IsDestroying() const {
return mIsDestroyingWindow;
}
// Utility methods
virtual PRBool OnExpose(nsPaintEvent &event);
virtual PRBool OnDraw(nsPaintEvent &event);
PRBool OnKey(nsKeyEvent &aEvent);
virtual PRBool OnScroll(nsScrollbarEvent & aEvent, PRUint32 cPos);
// in nsWidget now
// virtual PRBool OnResize(nsSizeEvent &aEvent);
static void SuperWinFilter(GdkSuperWin *superwin, XEvent *event, gpointer p);
void HandleXlibExposeEvent(XEvent *event);
void HandleXlibConfigureNotifyEvent(XEvent *event);
void HandleXlibButtonEvent(XButtonEvent *aButtonEvent);
void HandleXlibMotionNotifyEvent(XMotionEvent *aMotionEvent);
void HandleXlibCrossingEvent(XCrossingEvent * aCrossingEvent);
// Return the GtkMozArea that is the nearest parent of this widget
GtkWidget *GetMozArea();
// Return the Gdk window used for rendering
virtual GdkWindow * GetRenderWindow(GtkObject * aGtkWidget);
// XXX Chris - fix these
// virtual void OnButtonPressSignal(GdkEventButton * aGdkButtonEvent);
protected:
//////////////////////////////////////////////////////////////////////
//
// Draw signal
//
//////////////////////////////////////////////////////////////////////
void InitDrawEvent(GdkRectangle * aArea,
nsPaintEvent & aPaintEvent,
PRUint32 aEventType);
void UninitDrawEvent(GdkRectangle * area,
nsPaintEvent & aPaintEvent,
PRUint32 aEventType);
static gint DrawSignal(GtkWidget * aWidget,
GdkRectangle * aArea,
gpointer aData);
virtual gint OnDrawSignal(GdkRectangle * aArea);
virtual void OnRealize(GtkWidget *aWidget);
virtual void OnDestroySignal(GtkWidget* aGtkWidget);
//////////////////////////////////////////////////////////////////////
virtual void InitCallbacks(char * aName = nsnull);
NS_IMETHOD CreateNative(GtkObject *parentWidget);
nsIFontMetrics *mFontMetrics;
PRBool mVisible;
PRBool mDisplayed;
PRBool mIsDestroyingWindow;
PRBool mIsTooSmall;
// XXX Temporary, should not be caching the font
nsFont * mFont;
// Resize event management
nsRect mResizeRect;
int mResized;
PRBool mLowerLeft;
GtkWidget *mShell; /* used for toplevel windows */
GdkSuperWin *mSuperWin;
GtkWidget *mMozArea;
GtkWidget *mMozAreaClosestParent;
nsIMenuBar *mMenuBar;
private:
nsresult SetIcon(GdkPixmap *window_pixmap,
GdkBitmap *window_mask);
nsresult SetIcon();
PRBool mIsUpdating;
// this is the current GdkSuperWin with the focus
static nsWindow *focusWindow;
// when this is PR_TRUE we will block focus
// events to prevent recursion
PRBool mBlockFocusEvents;
};
//
// A child window is a window with different style
//
class ChildWindow : public nsWindow {
public:
ChildWindow();
~ChildWindow();
virtual PRBool IsChild() const;
#ifndef USE_SUPERWIN
NS_IMETHOD Destroy(void);
#endif
};
#endif // Window_h__