mirror of
https://github.com/gryf/wmaker.git
synced 2026-02-08 01:15:56 +01:00
Initial revision
This commit is contained in:
96
WINGs/ChangeLog
Normal file
96
WINGs/ChangeLog
Normal file
@@ -0,0 +1,96 @@
|
||||
changes since wmaker 0.20.0:
|
||||
............................
|
||||
|
||||
- changed WMGetFilePanelFile() with WMGetFilePanelFileName()
|
||||
- made SavePanel
|
||||
|
||||
changes since wmaker 0.19.3:
|
||||
............................
|
||||
|
||||
- added WMCreatePanelForWindow()
|
||||
- added extra parent parameter for filepanel, alertpanel and inputpanel
|
||||
- WMCloseWindow()
|
||||
- WMChangePanelOwner()
|
||||
- added WMAddInputHandler()
|
||||
- change range related function arguments (WMTextField) to use WMRange
|
||||
|
||||
changes since wmaker 0.19.1:
|
||||
............................
|
||||
|
||||
- added wstrappend()
|
||||
- fixed bug when changing selected radio button by hand
|
||||
|
||||
changes since wmaker 0.18.1:
|
||||
............................
|
||||
|
||||
- removed textHeight arg from W_PaintImageAndText
|
||||
- added WMCreateWindowWithStyle()
|
||||
- added WMSetWindowBaseSize() and ResizeIncrements()
|
||||
- added WMSetWindowLeve()
|
||||
- added WMSetWindowDocumentEdited()
|
||||
- added WMSetScrollViewLineScroll(), WMSetScrollViewPageScroll()
|
||||
- added WMSetWindowMiniwindowTitle()
|
||||
- added WMSetWindowMiniwindowImage()
|
||||
|
||||
changes since wmaker 0.18.0:
|
||||
............................
|
||||
|
||||
- added functions to get RGB components and "#rrggbb" string from WMColor.
|
||||
- added function to create color from a name
|
||||
- fixed bug that caused blocking until some new event arrives, even
|
||||
when there already were events in the queue
|
||||
(like having to move the pointer over window to force the window to be
|
||||
painted)
|
||||
|
||||
changes since wmaker 0.17.5:
|
||||
............................
|
||||
|
||||
I don't remember everything, but here it goes:
|
||||
|
||||
- fixed some bugs in text field
|
||||
- added a incomplete implementation of split view (not yet usable)
|
||||
- added a slider
|
||||
- changed the filepanel stuff. Each application can have only 1 file panel.
|
||||
The same panel will be reused every time you call for it, unless you free it.
|
||||
- changed semantics of WMCreateFont() so that it returns NULL if the requested
|
||||
font can't be loaded
|
||||
- removed WMAddDestroyCallback()
|
||||
- fixed bug in WMRemovePopUpButtonItem()
|
||||
- added function for user specified item height in WMList
|
||||
- added WMSetPopUpButtonText(). It will set the default text in the button
|
||||
when no options are selected
|
||||
- fixed bug in remove/add item in already mapped popupbuttons. Note: it is
|
||||
not good practice to change the contents of a popup button when it's
|
||||
already visible and the user has probably interacted with it.
|
||||
- fixed behaviour of "radio buttons"
|
||||
- WMInitializeApplication() must be the first function to be called in the
|
||||
program
|
||||
- removed applicationName, argc and argv arguments from the WMCreateScree...
|
||||
functions
|
||||
- WMReleaseColor(scr,color) changed to WMReleaseColor(color)
|
||||
- WMPaintColorRectangle() changed to WMPaintColorSwatch()
|
||||
- added various functions in font and color handling
|
||||
- added WMSetButtonFont()
|
||||
- changed WMCreateCommandButton() so that the buttons it creates will change
|
||||
their label when pushed
|
||||
- added WMGetSystemPixmap(WMScreen *scr, int image)
|
||||
- added partial I18N support
|
||||
- added libPropList requirement and some related utility functions
|
||||
- added a interface to prooplist, so that it works as a user defaults db
|
||||
- added WMWidthOfString() (removed WMFontWidthOfString())
|
||||
- added WMDrawString()
|
||||
- added WMSetTextFieldSecure(WMTextField *tPtr, Bool flag)
|
||||
- WMGetListItem() will dup the returned string
|
||||
- removed need for ProgName being defined
|
||||
- rewrote hashtable stuff and made it available for outside use
|
||||
- added notification functions, with view resize notification
|
||||
- added WMSetWindowMinSize() and MaxSize()
|
||||
- text editing notification
|
||||
- added WMSetListPosition() etc.
|
||||
- added WMInsertBrowserItem()
|
||||
- the above 2 functions return WMListItem*, instead of Bool
|
||||
- rewrote browser
|
||||
- WMGetListItem() will return WMListItem*
|
||||
- removed WMGetListItems() and WMSetListItems()
|
||||
- fixed focus stuff for multi-window apps
|
||||
- changed all WMList function names that contained index to row
|
||||
90
WINGs/Makefile.am
Normal file
90
WINGs/Makefile.am
Normal file
@@ -0,0 +1,90 @@
|
||||
## automake input file for WINGs
|
||||
|
||||
AUTOMAKE_OPTIONS = no-dependencies
|
||||
|
||||
SUBDIRS = Resources
|
||||
|
||||
|
||||
LIBLIST= -L$(top_builddir)/wrlib -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ \
|
||||
-lm @LIBPL_LIBS@
|
||||
|
||||
|
||||
lib_LIBRARIES = libWINGs.a
|
||||
|
||||
include_HEADERS = WINGs.h WUtil.h WINGsP.h
|
||||
|
||||
noinst_PROGRAMS = wtest wmquery wmfile fontl testmywidget
|
||||
|
||||
testmywidget_SOURCES = testmywidget.c mywidget.c mywidget.h
|
||||
|
||||
testmywidget_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
fontl_SOURCES = fontl.c
|
||||
|
||||
fontl_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
wtest_SOURCES = wtest.c
|
||||
|
||||
wtest_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
wtest_DEPENDENCIES = libWINGs.a
|
||||
|
||||
wmfile_SOURCES = wmfile.c
|
||||
|
||||
wmfile_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
|
||||
wmquery_SOURCES = wmquery.c
|
||||
|
||||
wmquery_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
|
||||
EXTRA_DIST = logo.xpm
|
||||
|
||||
# wbutton.c
|
||||
libWINGs_a_SOURCES = \
|
||||
WINGs.h \
|
||||
WINGsP.h \
|
||||
configuration.c \
|
||||
international.c \
|
||||
notification.c \
|
||||
selection.c \
|
||||
userdefaults.c \
|
||||
wapplication.c \
|
||||
wbrowser.c \
|
||||
wbutton.c \
|
||||
wcolor.c \
|
||||
wcolorwell.c \
|
||||
wevent.c \
|
||||
wfilepanel.c \
|
||||
wframe.c \
|
||||
wfont.c \
|
||||
wfontpanel.c \
|
||||
widgets.c \
|
||||
wlabel.c \
|
||||
wlist.c \
|
||||
wmisc.c \
|
||||
wpanel.c \
|
||||
wpixmap.c \
|
||||
wpopupbutton.c \
|
||||
wscroller.c \
|
||||
wscrollview.c \
|
||||
wslider.c \
|
||||
wsplitview.c \
|
||||
wtextfield.c \
|
||||
wwindow.c \
|
||||
wview.c \
|
||||
error.c \
|
||||
findfile.c \
|
||||
hashtable.c \
|
||||
memory.c \
|
||||
usleep.c
|
||||
|
||||
##
|
||||
## Find a better way than $(GFXFLAGS) to inform widgets.c wich of
|
||||
## tiff or xpm images should be used
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/wrlib -I$(top_srcdir)/src @XCFLAGS@ \
|
||||
-DRESOURCE_PATH=\"$(datadir)/WINGs\" $(GFXFLAGS) -DDEBUG \
|
||||
@LIBPL_INC_PATH@
|
||||
|
||||
513
WINGs/Makefile.in
Normal file
513
WINGs/Makefile.in
Normal file
@@ -0,0 +1,513 @@
|
||||
# Makefile.in generated automatically by automake 1.3 from Makefile.am
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DISTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_alias = @host_alias@
|
||||
host_triplet = @host@
|
||||
CC = @CC@
|
||||
CPP_PATH = @CPP_PATH@
|
||||
DFLAGS = @DFLAGS@
|
||||
GFXFLAGS = @GFXFLAGS@
|
||||
GFXLIBS = @GFXLIBS@
|
||||
I18N = @I18N@
|
||||
I18N_MB = @I18N_MB@
|
||||
ICONEXT = @ICONEXT@
|
||||
INTLIBS = @INTLIBS@
|
||||
LIBPL_INC_PATH = @LIBPL_INC_PATH@
|
||||
LIBPL_LIBS = @LIBPL_LIBS@
|
||||
LN_S = @LN_S@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MOFILES = @MOFILES@
|
||||
NLSDIR = @NLSDIR@
|
||||
PACKAGE = @PACKAGE@
|
||||
RANLIB = @RANLIB@
|
||||
REDUCE_APPICONS = @REDUCE_APPICONS@
|
||||
SHAPE = @SHAPE@
|
||||
SOUND = @SOUND@
|
||||
VERSION = @VERSION@
|
||||
WPMOFILES = @WPMOFILES@
|
||||
XCFLAGS = @XCFLAGS@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
XLFLAGS = @XLFLAGS@
|
||||
XLIBS = @XLIBS@
|
||||
XSHM = @XSHM@
|
||||
X_EXTRA_LIBS = @X_EXTRA_LIBS@
|
||||
X_LOCALE = @X_LOCALE@
|
||||
pixmapdir = @pixmapdir@
|
||||
wprefsdir = @wprefsdir@
|
||||
|
||||
AUTOMAKE_OPTIONS = no-dependencies
|
||||
|
||||
SUBDIRS = Resources
|
||||
|
||||
LIBLIST= -L$(top_builddir)/wrlib -lwraster @XLFLAGS@ @GFXLIBS@ @XLIBS@ \
|
||||
-lm @LIBPL_LIBS@
|
||||
|
||||
lib_LIBRARIES = libWINGs.a
|
||||
|
||||
include_HEADERS = WINGs.h WUtil.h WINGsP.h
|
||||
|
||||
noinst_PROGRAMS = wtest wmquery wmfile fontl testmywidget
|
||||
|
||||
testmywidget_SOURCES = testmywidget.c mywidget.c mywidget.h
|
||||
|
||||
testmywidget_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
fontl_SOURCES = fontl.c
|
||||
|
||||
fontl_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
wtest_SOURCES = wtest.c
|
||||
|
||||
wtest_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
wtest_DEPENDENCIES = libWINGs.a
|
||||
|
||||
wmfile_SOURCES = wmfile.c
|
||||
|
||||
wmfile_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
wmquery_SOURCES = wmquery.c
|
||||
|
||||
wmquery_LDADD = -L. -lWINGs $(LIBLIST)
|
||||
|
||||
EXTRA_DIST = logo.xpm
|
||||
|
||||
# wbutton.c
|
||||
libWINGs_a_SOURCES = \
|
||||
WINGs.h \
|
||||
WINGsP.h \
|
||||
configuration.c \
|
||||
international.c \
|
||||
notification.c \
|
||||
selection.c \
|
||||
userdefaults.c \
|
||||
wapplication.c \
|
||||
wbrowser.c \
|
||||
wbutton.c \
|
||||
wcolor.c \
|
||||
wcolorwell.c \
|
||||
wevent.c \
|
||||
wfilepanel.c \
|
||||
wframe.c \
|
||||
wfont.c \
|
||||
wfontpanel.c \
|
||||
widgets.c \
|
||||
wlabel.c \
|
||||
wlist.c \
|
||||
wmisc.c \
|
||||
wpanel.c \
|
||||
wpixmap.c \
|
||||
wpopupbutton.c \
|
||||
wscroller.c \
|
||||
wscrollview.c \
|
||||
wslider.c \
|
||||
wsplitview.c \
|
||||
wtextfield.c \
|
||||
wwindow.c \
|
||||
wview.c \
|
||||
error.c \
|
||||
findfile.c \
|
||||
hashtable.c \
|
||||
memory.c \
|
||||
usleep.c
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/wrlib -I$(top_srcdir)/src @XCFLAGS@ \
|
||||
-DRESOURCE_PATH=\"$(datadir)/WINGs\" $(GFXFLAGS) -DDEBUG \
|
||||
@LIBPL_INC_PATH@
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = ../src/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
LIBRARIES = $(lib_LIBRARIES)
|
||||
|
||||
|
||||
DEFS = @DEFS@ -I. -I$(srcdir) -I../src
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
X_CFLAGS = @X_CFLAGS@
|
||||
X_LIBS = @X_LIBS@
|
||||
X_PRE_LIBS = @X_PRE_LIBS@
|
||||
libWINGs_a_LIBADD =
|
||||
libWINGs_a_OBJECTS = configuration.o international.o notification.o \
|
||||
selection.o userdefaults.o wapplication.o wbrowser.o wbutton.o wcolor.o \
|
||||
wcolorwell.o wevent.o wfilepanel.o wframe.o wfont.o wfontpanel.o \
|
||||
widgets.o wlabel.o wlist.o wmisc.o wpanel.o wpixmap.o wpopupbutton.o \
|
||||
wscroller.o wscrollview.o wslider.o wsplitview.o wtextfield.o wwindow.o \
|
||||
wview.o error.o findfile.o hashtable.o memory.o usleep.o
|
||||
AR = ar
|
||||
PROGRAMS = $(noinst_PROGRAMS)
|
||||
|
||||
wtest_OBJECTS = wtest.o
|
||||
wtest_LDFLAGS =
|
||||
wmquery_OBJECTS = wmquery.o
|
||||
wmquery_DEPENDENCIES =
|
||||
wmquery_LDFLAGS =
|
||||
wmfile_OBJECTS = wmfile.o
|
||||
wmfile_DEPENDENCIES =
|
||||
wmfile_LDFLAGS =
|
||||
fontl_OBJECTS = fontl.o
|
||||
fontl_DEPENDENCIES =
|
||||
fontl_LDFLAGS =
|
||||
testmywidget_OBJECTS = testmywidget.o mywidget.o
|
||||
testmywidget_DEPENDENCIES =
|
||||
testmywidget_LDFLAGS =
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
|
||||
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
HEADERS = $(include_HEADERS)
|
||||
|
||||
DIST_COMMON = README ChangeLog Makefile.am Makefile.in TODO
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = tar
|
||||
GZIP = --best
|
||||
SOURCES = $(libWINGs_a_SOURCES) $(wtest_SOURCES) $(wmquery_SOURCES) $(wmfile_SOURCES) $(fontl_SOURCES) $(testmywidget_SOURCES)
|
||||
OBJECTS = $(libWINGs_a_OBJECTS) $(wtest_OBJECTS) $(wmquery_OBJECTS) $(wmfile_OBJECTS) $(fontl_OBJECTS) $(testmywidget_OBJECTS)
|
||||
|
||||
all: all-recursive all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .S .c .o .s
|
||||
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --gnu WINGs/Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
|
||||
mostlyclean-libLIBRARIES:
|
||||
|
||||
clean-libLIBRARIES:
|
||||
-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
|
||||
|
||||
distclean-libLIBRARIES:
|
||||
|
||||
maintainer-clean-libLIBRARIES:
|
||||
|
||||
install-libLIBRARIES: $(lib_LIBRARIES)
|
||||
@$(NORMAL_INSTALL)
|
||||
$(mkinstalldirs) $(DESTDIR)$(libdir)
|
||||
list='$(lib_LIBRARIES)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
echo " $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p"; \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p; \
|
||||
else :; fi; \
|
||||
done
|
||||
@$(POST_INSTALL)
|
||||
@list='$(lib_LIBRARIES)'; for p in $$list; do \
|
||||
if test -f $$p; then \
|
||||
echo " $(RANLIB) $(DESTDIR)$(libdir)/$$p"; \
|
||||
$(RANLIB) $(DESTDIR)$(libdir)/$$p; \
|
||||
else :; fi; \
|
||||
done
|
||||
|
||||
uninstall-libLIBRARIES:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
list='$(lib_LIBRARIES)'; for p in $$list; do \
|
||||
rm -f $(DESTDIR)$(libdir)/$$p; \
|
||||
done
|
||||
|
||||
.c.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.s.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
.S.o:
|
||||
$(COMPILE) -c $<
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.o core *.core
|
||||
|
||||
clean-compile:
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
maintainer-clean-compile:
|
||||
|
||||
libWINGs.a: $(libWINGs_a_OBJECTS) $(libWINGs_a_DEPENDENCIES)
|
||||
-rm -f libWINGs.a
|
||||
$(AR) cru libWINGs.a $(libWINGs_a_OBJECTS) $(libWINGs_a_LIBADD)
|
||||
$(RANLIB) libWINGs.a
|
||||
|
||||
mostlyclean-noinstPROGRAMS:
|
||||
|
||||
clean-noinstPROGRAMS:
|
||||
-test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
|
||||
|
||||
distclean-noinstPROGRAMS:
|
||||
|
||||
maintainer-clean-noinstPROGRAMS:
|
||||
|
||||
wtest: $(wtest_OBJECTS) $(wtest_DEPENDENCIES)
|
||||
@rm -f wtest
|
||||
$(LINK) $(wtest_LDFLAGS) $(wtest_OBJECTS) $(wtest_LDADD) $(LIBS)
|
||||
|
||||
wmquery: $(wmquery_OBJECTS) $(wmquery_DEPENDENCIES)
|
||||
@rm -f wmquery
|
||||
$(LINK) $(wmquery_LDFLAGS) $(wmquery_OBJECTS) $(wmquery_LDADD) $(LIBS)
|
||||
|
||||
wmfile: $(wmfile_OBJECTS) $(wmfile_DEPENDENCIES)
|
||||
@rm -f wmfile
|
||||
$(LINK) $(wmfile_LDFLAGS) $(wmfile_OBJECTS) $(wmfile_LDADD) $(LIBS)
|
||||
|
||||
fontl: $(fontl_OBJECTS) $(fontl_DEPENDENCIES)
|
||||
@rm -f fontl
|
||||
$(LINK) $(fontl_LDFLAGS) $(fontl_OBJECTS) $(fontl_LDADD) $(LIBS)
|
||||
|
||||
testmywidget: $(testmywidget_OBJECTS) $(testmywidget_DEPENDENCIES)
|
||||
@rm -f testmywidget
|
||||
$(LINK) $(testmywidget_LDFLAGS) $(testmywidget_OBJECTS) $(testmywidget_LDADD) $(LIBS)
|
||||
|
||||
install-includeHEADERS: $(include_HEADERS)
|
||||
@$(NORMAL_INSTALL)
|
||||
$(mkinstalldirs) $(DESTDIR)$(includedir)
|
||||
@list='$(include_HEADERS)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
|
||||
echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p"; \
|
||||
$(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/$$p; \
|
||||
done
|
||||
|
||||
uninstall-includeHEADERS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
list='$(include_HEADERS)'; for p in $$list; do \
|
||||
rm -f $(DESTDIR)$(includedir)/$$p; \
|
||||
done
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
# To change the values of `make' variables: instead of editing Makefiles,
|
||||
# (1) if the variable is set in `config.status', edit `config.status'
|
||||
# (which will cause the Makefiles to be regenerated when you run `make');
|
||||
# (2) otherwise, pass the desired values on the `make' command line.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
all-recursive install-data-recursive install-exec-recursive \
|
||||
installdirs-recursive install-recursive uninstall-recursive \
|
||||
check-recursive installcheck-recursive info-recursive dvi-recursive:
|
||||
@set fnord $(MAKEFLAGS); amf=$$2; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
(cd $$subdir && $(MAKE) $$target) \
|
||||
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done && test -z "$$fail"
|
||||
|
||||
mostlyclean-recursive clean-recursive distclean-recursive \
|
||||
maintainer-clean-recursive:
|
||||
@set fnord $(MAKEFLAGS); amf=$$2; \
|
||||
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
rev="$$subdir $$rev"; \
|
||||
done; \
|
||||
for subdir in $$rev; do \
|
||||
target=`echo $@ | sed s/-recursive//`; \
|
||||
echo "Making $$target in $$subdir"; \
|
||||
(cd $$subdir && $(MAKE) $$target) \
|
||||
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done && test -z "$$fail"
|
||||
tags-recursive:
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
(cd $$subdir && $(MAKE) tags); \
|
||||
done
|
||||
|
||||
tags: TAGS
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP)
|
||||
here=`pwd` && cd $(srcdir) \
|
||||
&& mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP)
|
||||
|
||||
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SUBDIRS)'; for subdir in $$list; do \
|
||||
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
|
||||
done; \
|
||||
list='$(SOURCES) $(HEADERS)'; \
|
||||
unique=`for i in $$list; do echo $$i; done | \
|
||||
awk ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|
||||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
|
||||
|
||||
mostlyclean-tags:
|
||||
|
||||
clean-tags:
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID
|
||||
|
||||
maintainer-clean-tags:
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = WINGs
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||
done
|
||||
for subdir in $(SUBDIRS); do \
|
||||
test -d $(distdir)/$$subdir \
|
||||
|| mkdir $(distdir)/$$subdir \
|
||||
|| exit 1; \
|
||||
chmod 777 $(distdir)/$$subdir; \
|
||||
(cd $$subdir && $(MAKE) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \
|
||||
|| exit 1; \
|
||||
done
|
||||
info: info-recursive
|
||||
dvi: dvi-recursive
|
||||
check: all-am
|
||||
$(MAKE) check-recursive
|
||||
installcheck: installcheck-recursive
|
||||
all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS)
|
||||
|
||||
install-exec-am: install-libLIBRARIES
|
||||
|
||||
install-data-am: install-includeHEADERS
|
||||
|
||||
uninstall-am: uninstall-libLIBRARIES uninstall-includeHEADERS
|
||||
|
||||
install-exec: install-exec-recursive install-exec-am
|
||||
@$(NORMAL_INSTALL)
|
||||
|
||||
install-data: install-data-recursive install-data-am
|
||||
@$(NORMAL_INSTALL)
|
||||
|
||||
install: install-recursive install-exec-am install-data-am
|
||||
@:
|
||||
|
||||
uninstall: uninstall-recursive uninstall-am
|
||||
|
||||
install-strip:
|
||||
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
|
||||
installdirs: installdirs-recursive
|
||||
$(mkinstalldirs) $(DATADIR)$(libdir) $(DATADIR)$(includedir)
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(DISTCLEANFILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||
mostlyclean-am: mostlyclean-libLIBRARIES mostlyclean-compile \
|
||||
mostlyclean-noinstPROGRAMS mostlyclean-tags \
|
||||
mostlyclean-generic
|
||||
|
||||
clean-am: clean-libLIBRARIES clean-compile clean-noinstPROGRAMS \
|
||||
clean-tags clean-generic mostlyclean-am
|
||||
|
||||
distclean-am: distclean-libLIBRARIES distclean-compile \
|
||||
distclean-noinstPROGRAMS distclean-tags \
|
||||
distclean-generic clean-am
|
||||
|
||||
maintainer-clean-am: maintainer-clean-libLIBRARIES \
|
||||
maintainer-clean-compile \
|
||||
maintainer-clean-noinstPROGRAMS maintainer-clean-tags \
|
||||
maintainer-clean-generic distclean-am
|
||||
|
||||
mostlyclean: mostlyclean-recursive mostlyclean-am
|
||||
|
||||
clean: clean-recursive clean-am
|
||||
|
||||
distclean: distclean-recursive distclean-am
|
||||
-rm -f config.status
|
||||
|
||||
maintainer-clean: maintainer-clean-recursive maintainer-clean-am
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
.PHONY: mostlyclean-libLIBRARIES distclean-libLIBRARIES \
|
||||
clean-libLIBRARIES maintainer-clean-libLIBRARIES uninstall-libLIBRARIES \
|
||||
install-libLIBRARIES mostlyclean-compile distclean-compile \
|
||||
clean-compile maintainer-clean-compile mostlyclean-noinstPROGRAMS \
|
||||
distclean-noinstPROGRAMS clean-noinstPROGRAMS \
|
||||
maintainer-clean-noinstPROGRAMS uninstall-includeHEADERS \
|
||||
install-includeHEADERS install-data-recursive uninstall-data-recursive \
|
||||
install-exec-recursive uninstall-exec-recursive installdirs-recursive \
|
||||
uninstalldirs-recursive all-recursive check-recursive \
|
||||
installcheck-recursive info-recursive dvi-recursive \
|
||||
mostlyclean-recursive distclean-recursive clean-recursive \
|
||||
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
|
||||
distclean-tags clean-tags maintainer-clean-tags distdir info dvi \
|
||||
installcheck all-am install-exec-am install-data-am uninstall-am \
|
||||
install-exec install-data install uninstall all installdirs \
|
||||
mostlyclean-generic distclean-generic clean-generic \
|
||||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
102
WINGs/README
Normal file
102
WINGs/README
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
WINGs - WINGs Is Not GNUstep
|
||||
|
||||
by
|
||||
|
||||
Alfredo Kengi Kojima
|
||||
|
||||
kojima@windowmaker.org
|
||||
|
||||
|
||||
WINGs is a small widget set with the N*XTSTEP look and feel. It's API
|
||||
is inspired in OpenStep and it's implementation borrows some ideas
|
||||
from Tk. It has a reasonable set of widgets, sufficient for building
|
||||
small applications (like a CDPlayer or hacking something like rxvt). It
|
||||
also has other functions that are usefull for applications, like a
|
||||
User Defaults like configuration manager and a notification system.
|
||||
|
||||
The library is limited and it's design is a little sloppy,
|
||||
so it's not intended to build large or complex applications, like
|
||||
anything more complex than a CDPlayer. GNUstep should be used for such
|
||||
applications.
|
||||
|
||||
Since WINGs is written in C and is sort of low-level it is small
|
||||
and faster than say, Motif or even Athena. Knowing Xlib will help you to
|
||||
workaround some of it's limitations, although you'll probably be able to
|
||||
write something like a trivial tic-tac-toe game without knowing much Xlib.
|
||||
|
||||
Some of it's functions are designed to support the WindowMaker window
|
||||
manager (see http://windowmaker.org) In fact, it's primary role is to
|
||||
support WindowMaker. All other uses of it are just an added bonus.
|
||||
|
||||
It will help you to understand the API if you read the ApplicationKit
|
||||
reference manual, distributed as a PDF by Apple. The function names,
|
||||
structs and most of the intrinsics are very close to OpenStep classes.
|
||||
|
||||
|
||||
Internationalization:
|
||||
---------------------
|
||||
|
||||
WINGs supports display of multibyte characters (kanji etc) without the
|
||||
to specify any flags (ie: there is no way to disable i18n support).
|
||||
Change ~/GNUstep/Defaults/WMGLOBAL to set the desired font set.
|
||||
|
||||
|
||||
Widgets provided by WINGs:
|
||||
--------------------------
|
||||
|
||||
- button (command button, radio, switch etc. - all buttons defined in OpenStep)
|
||||
- label
|
||||
- textfield
|
||||
- frame
|
||||
- window
|
||||
- popup menu button
|
||||
- scroller
|
||||
- selection list
|
||||
- browser
|
||||
- slider
|
||||
- scrollable view
|
||||
- color well
|
||||
- split view (only 2 subviews)
|
||||
|
||||
- input box
|
||||
- file panel
|
||||
- alert panel
|
||||
|
||||
Planned:
|
||||
--------
|
||||
|
||||
- selection (pasteboard like)
|
||||
- drag&drop
|
||||
|
||||
If you think you can code the following, please do. They are needed by
|
||||
WPrefs.app, but the number of other things I have to do is huge.
|
||||
|
||||
- color panel
|
||||
- font panel (the UI part is done. Might require a rewrite of the font list
|
||||
retrievel code. Might also require a WMFontManager)
|
||||
- input method support (XIM). I have no idea of how to code it. People who use
|
||||
different characters than ASCII will have trouble editing menus without it...
|
||||
|
||||
|
||||
Wish list: (I don't have the know-how or time to do them)
|
||||
---------------------------------------------------------
|
||||
|
||||
- text (with support for RTF)
|
||||
- matrix (like NSMatrix)
|
||||
- splitviews with more than 2 subviews
|
||||
- font manager (like NSFontManager)
|
||||
- finish file panel, open/save
|
||||
- finish other wigets
|
||||
- optimize list scrolling (XCopyArea() the area that's already drawn)
|
||||
- InterfaceMaker?
|
||||
- use XSetWMName and XSetWMIconName for the window/icon title setting.
|
||||
This requires transforming the received text to a text property with
|
||||
the proper encoding.
|
||||
|
||||
Copyright
|
||||
---------
|
||||
|
||||
WINGs is copyright (c) Alfredo K. Kojima and is licensed through the GNU
|
||||
Library General Public License (LGPL).
|
||||
|
||||
BIN
WINGs/Resources/Images.tiff
Normal file
BIN
WINGs/Resources/Images.tiff
Normal file
Binary file not shown.
BIN
WINGs/Resources/Images.xcf
Normal file
BIN
WINGs/Resources/Images.xcf
Normal file
Binary file not shown.
236
WINGs/Resources/Images.xpm
Normal file
236
WINGs/Resources/Images.xpm
Normal file
@@ -0,0 +1,236 @@
|
||||
/* XPM */
|
||||
static char * image_name[] = {
|
||||
"128 128 105 2",
|
||||
" c None",
|
||||
". c #000000000000",
|
||||
"X c #10400C301040",
|
||||
"o c #410345144103",
|
||||
"O c #DF7DE38DE79D",
|
||||
"+ c #18611C712081",
|
||||
"@ c #28A224922081",
|
||||
"# c #69A65D756185",
|
||||
"$ c #38E338E338E3",
|
||||
"% c #618565956185",
|
||||
"& c #CF3CD34CD75C",
|
||||
"* c #C71BCB2BCF3C",
|
||||
"= c #208120812081",
|
||||
"- c #492455555965",
|
||||
"; c #9E7975D671C6",
|
||||
": c #492445144103",
|
||||
"> c #28A220811861",
|
||||
", c #8E3892489658",
|
||||
"< c #D75CDB6CDF7D",
|
||||
"1 c #BEFBCB2BCF3C",
|
||||
"2 c #BEFBC30BC71B",
|
||||
"3 c #186114511861",
|
||||
"4 c #208124922081",
|
||||
"5 c #38E32CB228A2",
|
||||
"6 c #61855D755144",
|
||||
"7 c #4924451438E3",
|
||||
"8 c #410330C228A2",
|
||||
"9 c #A699AAAAAEBA",
|
||||
"0 c #69A669A66185",
|
||||
"q c #41033CF338E3",
|
||||
"w c #69A661855965",
|
||||
"e c #618559655144",
|
||||
"r c #38E334D330C2",
|
||||
"t c #69A661856185",
|
||||
"y c #96589A699E79",
|
||||
"u c #082004100820",
|
||||
"i c #596555555144",
|
||||
"p c #618561855965",
|
||||
"a c #514451444924",
|
||||
"s c #96588E388E38",
|
||||
"d c #86178A288E38",
|
||||
"f c #8E388A288617",
|
||||
"g c #965892489658",
|
||||
"h c #B6DABAEABEFB",
|
||||
"j c #69A669A669A6",
|
||||
"k c #51443CF338E3",
|
||||
"l c #71C671C669A6",
|
||||
"z c #AEBAAAAAAEBA",
|
||||
"x c #AEBAB2CAB6DA",
|
||||
"c c #9E79A289A699",
|
||||
"v c #861782078617",
|
||||
"b c #71C679E779E7",
|
||||
"n c #96589E79A699",
|
||||
"m c #410341034103",
|
||||
"M c #492449244924",
|
||||
"N c #79E782078617",
|
||||
"B c #965896589658",
|
||||
"V c #104008200820",
|
||||
"C c #9E799E799E79",
|
||||
"Z c #30C230C228A2",
|
||||
"A c #596559655965",
|
||||
"S c #8E388E389658",
|
||||
"D c #38E33CF34103",
|
||||
"F c #8617820779E7",
|
||||
"G c #AEBAA6999E79",
|
||||
"H c #38E33CF338E3",
|
||||
"J c #79E7820779E7",
|
||||
"K c #8E388E388E38",
|
||||
"L c #186118611861",
|
||||
"P c #20811C711861",
|
||||
"I c #A699A2899E79",
|
||||
"U c #E79DEBADEFBE",
|
||||
"Y c #861775D669A6",
|
||||
"T c #EFBEF7DEF7DE",
|
||||
"R c #BEFBBEFBBEFB",
|
||||
"E c #9E799A699E79",
|
||||
"W c #71C675D671C6",
|
||||
"Q c #186114511040",
|
||||
"! c #28A22CB228A2",
|
||||
"~ c #49244D344924",
|
||||
"^ c #69A66DB669A6",
|
||||
"/ c #965892488E38",
|
||||
"( c #79E77DF78617",
|
||||
") c #A699A699A699",
|
||||
"_ c #79E779E771C6",
|
||||
"` c #CF3CCB2BCF3C",
|
||||
"' c #8E388A288E38",
|
||||
"] c #79E77DF779E7",
|
||||
"[ c #4103410338E3",
|
||||
"{ c #30C22CB228A2",
|
||||
"} c #30C228A228A2",
|
||||
"| c #514455555144",
|
||||
" . c #71C659655144",
|
||||
".. c #492434D330C2",
|
||||
"X. c #596561856185",
|
||||
"o. c #69A651444924",
|
||||
"O. c #514449244103",
|
||||
"+. c #59655D756185",
|
||||
"@. c #A6998E388617",
|
||||
"#. c #49243CF338E3",
|
||||
"$. c #38E324922081",
|
||||
"%. c #38E32CB22081",
|
||||
"&. c #104014511040",
|
||||
"*. c #30C228A22081",
|
||||
"=. c #28A214511040",
|
||||
" ",
|
||||
" . ",
|
||||
" . X o O + . ",
|
||||
" @ # . . X $ % & & * = . ",
|
||||
" - ; = : > , < 1 1 & 2 3 . ",
|
||||
" 4 X . . 5 6 7 8 * < 1 2 & 2 2 9 X . ",
|
||||
" = 0 q w 0 e r t < O < & & & & & < y u . ",
|
||||
" i O r p a p s , , d f g g 9 9 h < & j u . ",
|
||||
". k l z g h 2 * x & O & z h * c c v b n m . ",
|
||||
". M N & m 1 B g 2 & 1 & V C O Z A < 1 S = u . ",
|
||||
" D F & p * c G 2 < < < r 2 O H J < 2 K L . ",
|
||||
" D q * P < B I 2 U U U Y & T r , U O R = . ",
|
||||
" D E < 2 & & U y W Q u ! o ~ W ^ @ Q ~ / = . ",
|
||||
" o O O O < < O d * h E B ( ) y J _ A h c ~ X . ",
|
||||
"m ` d h m < ' 2 ' o P v V @ Z o ~ y b J ] W = . ",
|
||||
". U W 2 M O g & B 0 Q ' Q [ { } r | = | > r 4 . ",
|
||||
". T { x r O b & c Y .' Q = a > a % ..v | ~ = . ",
|
||||
". U 9 2 y < c x c % N , 6 X.o.O., 9 ^ a +.^ = . ",
|
||||
". ] ' h 9 * h x @.h 2 h N J c | ( 2 F a , y = . ",
|
||||
". ! Z w p j #.} } > } = { W $.[ r r Z ~ m %.4 . ",
|
||||
" . &.= 4 = { a A r *.> =.= *.{ { { r { { Z 4 . ",
|
||||
" . . . . u X Q L = 4 4 4 = = = = = = = = L . ",
|
||||
" . . . . . . . . . . . . . . . . . ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
6
WINGs/Resources/Makefile.am
Normal file
6
WINGs/Resources/Makefile.am
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
resdatadir = $(datadir)/WINGs
|
||||
|
||||
resdata_DATA = Images.tiff Images.xpm defaultIcon.tiff defaultIcon.xpm
|
||||
|
||||
EXTRA_DIST = $(resdata_DATA) Images.xcf
|
||||
210
WINGs/Resources/Makefile.in
Normal file
210
WINGs/Resources/Makefile.in
Normal file
@@ -0,0 +1,210 @@
|
||||
# Makefile.in generated automatically by automake 1.3 from Makefile.am
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
SHELL = /bin/sh
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = /usr/include
|
||||
|
||||
DISTDIR =
|
||||
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
|
||||
top_builddir = ../..
|
||||
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
transform = @program_transform_name@
|
||||
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_alias = @host_alias@
|
||||
host_triplet = @host@
|
||||
CC = @CC@
|
||||
CPP_PATH = @CPP_PATH@
|
||||
DFLAGS = @DFLAGS@
|
||||
GFXFLAGS = @GFXFLAGS@
|
||||
GFXLIBS = @GFXLIBS@
|
||||
I18N = @I18N@
|
||||
I18N_MB = @I18N_MB@
|
||||
ICONEXT = @ICONEXT@
|
||||
INTLIBS = @INTLIBS@
|
||||
LIBPL_INC_PATH = @LIBPL_INC_PATH@
|
||||
LIBPL_LIBS = @LIBPL_LIBS@
|
||||
LN_S = @LN_S@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MOFILES = @MOFILES@
|
||||
NLSDIR = @NLSDIR@
|
||||
PACKAGE = @PACKAGE@
|
||||
RANLIB = @RANLIB@
|
||||
REDUCE_APPICONS = @REDUCE_APPICONS@
|
||||
SHAPE = @SHAPE@
|
||||
SOUND = @SOUND@
|
||||
VERSION = @VERSION@
|
||||
WPMOFILES = @WPMOFILES@
|
||||
XCFLAGS = @XCFLAGS@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
XLFLAGS = @XLFLAGS@
|
||||
XLIBS = @XLIBS@
|
||||
XSHM = @XSHM@
|
||||
X_EXTRA_LIBS = @X_EXTRA_LIBS@
|
||||
X_LOCALE = @X_LOCALE@
|
||||
pixmapdir = @pixmapdir@
|
||||
wprefsdir = @wprefsdir@
|
||||
|
||||
resdatadir = $(datadir)/WINGs
|
||||
|
||||
resdata_DATA = Images.tiff Images.xpm defaultIcon.tiff defaultIcon.xpm
|
||||
|
||||
EXTRA_DIST = $(resdata_DATA) Images.xcf
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = ../../src/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
DATA = $(resdata_DATA)
|
||||
|
||||
DIST_COMMON = Makefile.am Makefile.in
|
||||
|
||||
|
||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
TAR = tar
|
||||
GZIP = --best
|
||||
all: Makefile $(DATA)
|
||||
|
||||
.SUFFIXES:
|
||||
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps WINGs/Resources/Makefile
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
|
||||
|
||||
install-resdataDATA: $(resdata_DATA)
|
||||
@$(NORMAL_INSTALL)
|
||||
$(mkinstalldirs) $(DESTDIR)$(resdatadir)
|
||||
@list='$(resdata_DATA)'; for p in $$list; do \
|
||||
if test -f $(srcdir)/$$p; then \
|
||||
echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(resdatadir)/$$p"; \
|
||||
$(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(resdatadir)/$$p; \
|
||||
else if test -f $$p; then \
|
||||
echo " $(INSTALL_DATA) $$p $(DESTDIR)$(resdatadir)/$$p"; \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(resdatadir)/$$p; \
|
||||
fi; fi; \
|
||||
done
|
||||
|
||||
uninstall-resdataDATA:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
list='$(resdata_DATA)'; for p in $$list; do \
|
||||
rm -f $(DESTDIR)$(resdatadir)/$$p; \
|
||||
done
|
||||
tags: TAGS
|
||||
TAGS:
|
||||
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
|
||||
subdir = WINGs/Resources
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@for file in $(DISTFILES); do \
|
||||
d=$(srcdir); \
|
||||
test -f $(distdir)/$$file \
|
||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file; \
|
||||
done
|
||||
info:
|
||||
dvi:
|
||||
check: all
|
||||
$(MAKE)
|
||||
installcheck:
|
||||
install-exec:
|
||||
@$(NORMAL_INSTALL)
|
||||
|
||||
install-data: install-resdataDATA
|
||||
@$(NORMAL_INSTALL)
|
||||
|
||||
install: install-exec install-data all
|
||||
@:
|
||||
|
||||
uninstall: uninstall-resdataDATA
|
||||
|
||||
install-strip:
|
||||
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install
|
||||
installdirs:
|
||||
$(mkinstalldirs) $(DATADIR)$(resdatadir)
|
||||
|
||||
|
||||
mostlyclean-generic:
|
||||
-test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(DISTCLEANFILES)
|
||||
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
|
||||
mostlyclean: mostlyclean-generic
|
||||
|
||||
clean: clean-generic mostlyclean
|
||||
|
||||
distclean: distclean-generic clean
|
||||
-rm -f config.status
|
||||
|
||||
maintainer-clean: maintainer-clean-generic distclean
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
|
||||
.PHONY: uninstall-resdataDATA install-resdataDATA tags distdir info dvi \
|
||||
installcheck install-exec install-data install uninstall all \
|
||||
installdirs mostlyclean-generic distclean-generic clean-generic \
|
||||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
BIN
WINGs/Resources/defaultIcon.tiff
Normal file
BIN
WINGs/Resources/defaultIcon.tiff
Normal file
Binary file not shown.
54
WINGs/Resources/defaultIcon.xpm
Normal file
54
WINGs/Resources/defaultIcon.xpm
Normal file
@@ -0,0 +1,54 @@
|
||||
/* XPM */
|
||||
static char * defaultIcon_xpm[] = {
|
||||
"48 48 3 1",
|
||||
" c #000000000000",
|
||||
". c None",
|
||||
"X c #FFFFFFFFFFFF",
|
||||
" ..",
|
||||
" ..",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ..",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ",
|
||||
" ",
|
||||
" ",
|
||||
".... ",
|
||||
".... "};
|
||||
5
WINGs/TODO
Normal file
5
WINGs/TODO
Normal file
@@ -0,0 +1,5 @@
|
||||
- move paint to idle handlers
|
||||
|
||||
- optimize color allocation for repeated colors
|
||||
- make it work in 8bpp
|
||||
- optimize SystemFont allocation for repeated font sizes
|
||||
1004
WINGs/WINGs.h
Normal file
1004
WINGs/WINGs.h
Normal file
File diff suppressed because it is too large
Load Diff
394
WINGs/WINGsP.h
Normal file
394
WINGs/WINGsP.h
Normal file
@@ -0,0 +1,394 @@
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
|
||||
#include "WINGs.h"
|
||||
#include "WUtil.h"
|
||||
|
||||
#if WINGS_H_VERSION < 980922
|
||||
#error There_is_an_old_WINGs.h_file_somewhere_in_your_system._Please_remove_it.
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define DOUBLE_BUFFER
|
||||
|
||||
|
||||
|
||||
#define WC_UserWidget 128
|
||||
|
||||
|
||||
|
||||
#define SCROLLER_WIDTH 20
|
||||
|
||||
/* internal messages */
|
||||
#define WM_UPDATE_COLORWELL 130
|
||||
|
||||
|
||||
#define WM_USER_MESSAGE 1024
|
||||
|
||||
|
||||
#define SETUP_INTERNAL_MESSAGE(event, scrPtr) \
|
||||
event.xclient.type=ClientMessage;\
|
||||
event.xclient.display=scrPtr->display;\
|
||||
event.xclient.send_event=False;\
|
||||
event.xclient.serial=0;\
|
||||
event.xclient.format=32;\
|
||||
event.xclient.message_type=scrPtr->internalMessage;
|
||||
|
||||
|
||||
typedef struct W_Font {
|
||||
struct W_Screen *screen;
|
||||
|
||||
union {
|
||||
XFontSet set;
|
||||
XFontStruct *normal;
|
||||
} font;
|
||||
short height;
|
||||
short y;
|
||||
short refCount;
|
||||
unsigned int notFontSet:1;
|
||||
} W_Font;
|
||||
|
||||
|
||||
typedef struct W_Pixmap {
|
||||
struct W_Screen *screen;
|
||||
Pixmap pixmap;
|
||||
Pixmap mask;
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
short depth;
|
||||
short refCount;
|
||||
} W_Pixmap;
|
||||
|
||||
|
||||
typedef struct W_Color {
|
||||
struct W_Screen *screen;
|
||||
|
||||
XColor color;
|
||||
short refCount;
|
||||
GC gc;
|
||||
struct {
|
||||
unsigned int exact:1;
|
||||
} flags;
|
||||
} W_Color;
|
||||
|
||||
|
||||
typedef struct W_FocusInfo {
|
||||
struct W_View *toplevel;
|
||||
struct W_View *focused; /* view that has the focus in this toplevel */
|
||||
struct W_FocusInfo *next;
|
||||
} W_FocusInfo;
|
||||
|
||||
typedef struct W_Screen {
|
||||
Display *display;
|
||||
int screen;
|
||||
int depth;
|
||||
|
||||
Colormap colormap;
|
||||
|
||||
Visual *visual;
|
||||
|
||||
Time lastEventTime;
|
||||
|
||||
Window rootWin;
|
||||
|
||||
struct W_View *rootView;
|
||||
|
||||
RContext *rcontext;
|
||||
|
||||
/* application related */
|
||||
|
||||
W_FocusInfo *focusInfo;
|
||||
|
||||
struct W_Pixmap *applicationIcon;
|
||||
|
||||
struct W_Window *windowList; /* list of windows in the app */
|
||||
|
||||
Window groupLeader; /* the leader of the application */
|
||||
/* also used for other things */
|
||||
|
||||
struct W_SelectionHandlers *selectionHandlerList;
|
||||
|
||||
struct {
|
||||
unsigned int hasAppIcon:1;
|
||||
unsigned int simpleApplication:1;
|
||||
} aflags;
|
||||
|
||||
WMOpenPanel *sharedOpenPanel;
|
||||
WMSavePanel *sharedSavePanel;
|
||||
|
||||
struct W_FontPanel *sharedFontPanel;
|
||||
|
||||
struct W_ColorPanel *sharedColorPanel;
|
||||
|
||||
/* colors */
|
||||
W_Color *white;
|
||||
W_Color *black;
|
||||
W_Color *gray;
|
||||
W_Color *darkGray;
|
||||
|
||||
GC stippleGC;
|
||||
|
||||
GC copyGC;
|
||||
GC clipGC;
|
||||
|
||||
GC monoGC; /* GC for 1bpp visuals */
|
||||
|
||||
GC xorGC;
|
||||
|
||||
GC ixorGC; /* IncludeInferiors XOR */
|
||||
|
||||
GC textFieldGC;
|
||||
|
||||
W_Font *normalFont;
|
||||
|
||||
W_Font *boldFont;
|
||||
|
||||
struct W_Pixmap *checkButtonImageOn;
|
||||
struct W_Pixmap *checkButtonImageOff;
|
||||
|
||||
struct W_Pixmap *radioButtonImageOn;
|
||||
struct W_Pixmap *radioButtonImageOff;
|
||||
|
||||
struct W_Pixmap *buttonArrow;
|
||||
struct W_Pixmap *pushedButtonArrow;
|
||||
|
||||
struct W_Pixmap *scrollerDimple;
|
||||
|
||||
struct W_Pixmap *upArrow;
|
||||
struct W_Pixmap *downArrow;
|
||||
struct W_Pixmap *leftArrow;
|
||||
struct W_Pixmap *rightArrow;
|
||||
|
||||
struct W_Pixmap *hiUpArrow;
|
||||
struct W_Pixmap *hiDownArrow;
|
||||
struct W_Pixmap *hiLeftArrow;
|
||||
struct W_Pixmap *hiRightArrow;
|
||||
|
||||
struct W_Pixmap *pullDownIndicator;
|
||||
struct W_Pixmap *popUpIndicator;
|
||||
|
||||
struct W_Pixmap *homeIcon;
|
||||
|
||||
struct W_Pixmap *defaultObjectIcon;
|
||||
|
||||
Cursor defaultCursor;
|
||||
|
||||
Cursor textCursor;
|
||||
|
||||
Atom internalMessage; /* for ClientMessage */
|
||||
|
||||
Atom attribsAtom; /* GNUstepWindowAttributes */
|
||||
|
||||
Atom deleteWindowAtom; /* WM_DELETE_WINDOW */
|
||||
|
||||
Atom protocolsAtom; /* _XA_WM_PROTOCOLS */
|
||||
|
||||
Atom clipboardAtom; /* CLIPBOARD */
|
||||
|
||||
|
||||
/* stuff for detecting double-clicks */
|
||||
Time lastClickTime; /* time of last mousedown event */
|
||||
Window lastClickWindow; /* window of the last mousedown */
|
||||
|
||||
struct W_View *modalView;
|
||||
unsigned modal:1;
|
||||
unsigned ignoreNextDoubleClick:1;
|
||||
} W_Screen;
|
||||
|
||||
|
||||
|
||||
typedef struct W_View {
|
||||
struct W_Screen *screen;
|
||||
|
||||
WMWidget *self; /* must point to the widget the
|
||||
* view belongs to */
|
||||
|
||||
Window window;
|
||||
|
||||
WMSize size;
|
||||
|
||||
WMPoint pos;
|
||||
|
||||
struct W_View *nextFocusChain; /* next/prev in focus chain */
|
||||
struct W_View *prevFocusChain;
|
||||
|
||||
struct W_View *parent; /* parent WMView */
|
||||
|
||||
struct W_View *childrenList; /* first in list of child windows */
|
||||
|
||||
struct W_View *nextSister; /* next on parent's children list */
|
||||
|
||||
struct W_EventHandler *handlerList;/* list of event handlers for this window */
|
||||
|
||||
unsigned long attribFlags;
|
||||
XSetWindowAttributes attribs;
|
||||
|
||||
void *hangedData; /* data holder for user program */
|
||||
#if 0
|
||||
struct W_DragSourceProcs *dragSourceProcs;
|
||||
struct W_DragDestinationProcs *dragDestinationProcs;
|
||||
#endif
|
||||
int helpContext;
|
||||
|
||||
struct {
|
||||
unsigned int realized:1;
|
||||
unsigned int mapped:1;
|
||||
unsigned int parentDying:1;
|
||||
unsigned int dying:1; /* the view is being destroyed */
|
||||
unsigned int topLevel:1; /* is a top level window */
|
||||
unsigned int root:1; /* is the root window */
|
||||
unsigned int mapWhenRealized:1;/* map the view when it's realized */
|
||||
unsigned int alreadyDead:1; /* view was freed */
|
||||
|
||||
unsigned int dontCompressMotion:1; /* motion notify event compress */
|
||||
unsigned int notifySizeChanged:1;
|
||||
unsigned int dontCompressExpose:1; /* will compress all expose
|
||||
events into one */
|
||||
/* toplevel only */
|
||||
unsigned int worksWhenModal:1;
|
||||
unsigned int pendingRelease1:1;
|
||||
unsigned int pendingRelease2:1;
|
||||
unsigned int pendingRelease3:1;
|
||||
unsigned int pendingRelease4:1;
|
||||
unsigned int pendingRelease5:1;
|
||||
} flags;
|
||||
|
||||
int refCount;
|
||||
} W_View;
|
||||
|
||||
|
||||
typedef struct W_EventHandler {
|
||||
unsigned long eventMask;
|
||||
|
||||
WMEventProc *proc;
|
||||
|
||||
void *clientData;
|
||||
|
||||
struct W_EventHandler *nextHandler;
|
||||
} W_EventHandler;
|
||||
|
||||
|
||||
|
||||
typedef struct W_ViewProcedureTable {
|
||||
void (*setBackgroundColor)(WMWidget*, WMColor *color);
|
||||
void (*resize)(WMWidget*, unsigned int, unsigned int);
|
||||
void (*move)(WMWidget*, int, int);
|
||||
} W_ViewProcedureTable;
|
||||
|
||||
|
||||
|
||||
typedef struct _WINGsConfiguration {
|
||||
char *systemFont;
|
||||
char *boldSystemFont;
|
||||
unsigned doubleClickDelay;
|
||||
} _WINGsConfiguration;
|
||||
|
||||
_WINGsConfiguration WINGsConfiguration;
|
||||
|
||||
|
||||
|
||||
#define CHECK_CLASS(widget, class) assert(W_CLASS(widget)==(class))
|
||||
|
||||
|
||||
#define W_CLASS(widget) (((W_WidgetType*)(widget))->widgetClass)
|
||||
#define W_VIEW(widget) (((W_WidgetType*)(widget))->view)
|
||||
|
||||
#define W_VIEW_REALIZED(view) (view)->flags.realized
|
||||
#define W_VIEW_MAPPED(view) (view)->flags.mapped
|
||||
|
||||
#define W_PIXEL(c) (c)->color.pixel
|
||||
#define W_GC(c) (c)->gc
|
||||
|
||||
#define W_FONTID(f) (f)->font->fid
|
||||
|
||||
#define W_DRAWABLE(scr) (scr)->rootWin
|
||||
|
||||
|
||||
W_View *W_GetViewForXWindow(Display *display, Window window);
|
||||
|
||||
W_View *W_CreateView(W_View *parent);
|
||||
|
||||
W_View *W_CreateTopView(W_Screen *screen);
|
||||
|
||||
|
||||
W_View *W_CreateRootView(W_Screen *screen);
|
||||
|
||||
void W_DestroyView(W_View *view);
|
||||
|
||||
void W_RealizeView(W_View *view);
|
||||
|
||||
void W_ReparentView(W_View *view, W_View *newParent);
|
||||
|
||||
void W_MapView(W_View *view);
|
||||
|
||||
void W_MapSubviews(W_View *view);
|
||||
|
||||
void W_UnmapSubviews(W_View *view);
|
||||
|
||||
W_View *W_TopLevelOfView(W_View *view);
|
||||
|
||||
void W_UnmapView(W_View *view);
|
||||
|
||||
void W_MoveView(W_View *view, int x, int y);
|
||||
|
||||
void W_ResizeView(W_View *view, unsigned int width, unsigned int height);
|
||||
|
||||
void W_SetViewBackgroundColor(W_View *view, WMColor *color);
|
||||
|
||||
void W_DrawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
|
||||
unsigned int height, WMReliefType relief);
|
||||
|
||||
|
||||
void W_CleanUpEvents(W_View *view);
|
||||
|
||||
void W_CallDestroyHandlers(W_View *view);
|
||||
|
||||
void W_PaintTextAndImage(W_View *view, int wrap, GC textGC, W_Font *font,
|
||||
WMReliefType relief, char *text,
|
||||
WMAlignment alignment, W_Pixmap *image,
|
||||
WMImagePosition position, GC backGC, int ofs);
|
||||
|
||||
void W_PaintText(W_View *view, Drawable d, WMFont *font, int x, int y,
|
||||
int width, WMAlignment alignment, GC gc,
|
||||
int wrap, char *text, int length);
|
||||
|
||||
int W_GetTextHeight(WMFont *font, char *text, int width, int wrap);
|
||||
|
||||
|
||||
int W_TextWidth(WMFont *font, char *text, int length);
|
||||
|
||||
|
||||
void W_BroadcastMessage(W_View *targetParent, XEvent *event);
|
||||
|
||||
void W_DispatchMessage(W_View *target, XEvent *event);
|
||||
|
||||
Bool W_CheckInternalMessage(W_Screen *scr, XClientMessageEvent *cev, int event);
|
||||
|
||||
void W_SetFocusOfToplevel(W_View *toplevel, W_View *view);
|
||||
|
||||
W_View *W_FocusedViewOfToplevel(W_View *view);
|
||||
|
||||
void W_SetFocusOfTopLevel(W_View *toplevel, W_View *view);
|
||||
|
||||
void W_ReleaseView(WMView *view);
|
||||
|
||||
WMView *W_RetainView(WMView *view);
|
||||
|
||||
void W_InitApplication(WMScreen *scr);
|
||||
|
||||
void W_InitNotificationCenter(void);
|
||||
|
||||
W_Class W_RegisterUserWidget(W_ViewProcedureTable *procTable);
|
||||
|
||||
void W_RedisplayView(WMView *view);
|
||||
|
||||
Bool W_ApplicationInitialized(void);
|
||||
|
||||
char *W_GetTextSelection(WMScreen *scr, Atom selection);
|
||||
227
WINGs/WUtil.h
Normal file
227
WINGs/WUtil.h
Normal file
@@ -0,0 +1,227 @@
|
||||
#ifndef _WUTIL_H_
|
||||
#define _WUTIL_H_
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* Warning: proplist.h #defines BOOL which will clash with the
|
||||
* typedef BOOL in Xmd.h
|
||||
* proplist.h should use Bool (which is a #define in Xlib.h) instead.
|
||||
*
|
||||
*/
|
||||
#include <proplist.h>
|
||||
|
||||
|
||||
#ifndef WMAX
|
||||
# define WMAX(a,b) ((a)>(b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef WMIN
|
||||
# define WMIN(a,b) ((a)<(b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
WMPostWhenIdle = 1,
|
||||
WMPostASAP = 2,
|
||||
WMPostNow = 3
|
||||
} WMPostingStyle;
|
||||
|
||||
|
||||
typedef enum {
|
||||
WNCNone = 0,
|
||||
WNCOnName = 1,
|
||||
WNCOnSender = 2
|
||||
} WMNotificationCoalescing;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct W_HashTable WMHashTable;
|
||||
typedef struct W_UserDefaults WMUserDefaults;
|
||||
typedef struct W_Notification WMNotification;
|
||||
typedef struct W_NotificationQueue WMNotificationQueue;
|
||||
|
||||
|
||||
/* DO NOT ACCESS THE CONTENTS OF THIS STRUCT */
|
||||
typedef struct {
|
||||
void *table;
|
||||
void *nextItem;
|
||||
int index;
|
||||
} WMHashEnumerator;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* NULL is pointer hash */
|
||||
unsigned (*hash)(const void *);
|
||||
/* NULL is pointer compare */
|
||||
Bool (*keyIsEqual)(const void *, const void *);
|
||||
/* NULL does nothing */
|
||||
void* (*retainKey)(const void *);
|
||||
/* NULL does nothing */
|
||||
void (*releaseKey)(const void *);
|
||||
} WMHashTableCallbacks;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef void WMNotificationObserverAction(void *observerData,
|
||||
WMNotification *notification);
|
||||
|
||||
|
||||
|
||||
/*......................................................................*/
|
||||
|
||||
|
||||
void wfatal(const char *msg, ...);
|
||||
void wwarning(const char *msg, ...);
|
||||
void wsyserror(const char *msg, ...);
|
||||
|
||||
char *wfindfile(char *paths, char *file);
|
||||
|
||||
char *wfindfileinlist(char **path_list, char *file);
|
||||
|
||||
char *wexpandpath(char *path);
|
||||
|
||||
/* don't free the returned string */
|
||||
char *wgethomedir();
|
||||
|
||||
void *wmalloc(size_t size);
|
||||
void *wrealloc(void *ptr, size_t newsize);
|
||||
|
||||
void wrelease(void *ptr);
|
||||
void *wretain(void *ptr);
|
||||
|
||||
char *wstrdup(char *str);
|
||||
|
||||
char *wstrappend(char *dst, char *src);
|
||||
|
||||
char *wusergnusteppath();
|
||||
|
||||
char *wdefaultspathfordomain(char *domain);
|
||||
|
||||
void wusleep(unsigned int microsec);
|
||||
|
||||
/*......................................................................*/
|
||||
|
||||
|
||||
WMHashTable *WMCreateHashTable(WMHashTableCallbacks callbacks);
|
||||
|
||||
void WMFreeHashTable(WMHashTable *table);
|
||||
|
||||
void WMResetHashTable(WMHashTable *table);
|
||||
|
||||
void *WMHashGet(WMHashTable *table, const void *key);
|
||||
|
||||
/* put data in table, replacing already existing data and returning
|
||||
* the old value */
|
||||
void *WMHashInsert(WMHashTable *table, void *key, void *data);
|
||||
|
||||
void WMHashRemove(WMHashTable *table, const void *key);
|
||||
|
||||
/* warning: do not manipulate the table while using these functions */
|
||||
WMHashEnumerator WMEnumerateHashTable(WMHashTable *table);
|
||||
|
||||
void *WMNextHashEnumeratorItem(WMHashEnumerator *enumerator);
|
||||
|
||||
unsigned WMCountHashTable(WMHashTable *table);
|
||||
|
||||
|
||||
|
||||
|
||||
/* some predefined callback sets */
|
||||
|
||||
extern const WMHashTableCallbacks WMIntHashCallbacks;
|
||||
/* sizeof(keys) are <= sizeof(void*) */
|
||||
|
||||
extern const WMHashTableCallbacks WMStringHashCallbacks;
|
||||
/* keys are strings. Strings will be copied with wstrdup()
|
||||
* and freed with free() */
|
||||
|
||||
extern const WMHashTableCallbacks WMStringPointerHashCallbacks;
|
||||
/* keys are strings, bug they are not copied */
|
||||
|
||||
/*......................................................................*/
|
||||
|
||||
WMNotification *WMCreateNotification(char *name, void *object, void *clientData);
|
||||
|
||||
void WMReleaseNotification(WMNotification *notification);
|
||||
|
||||
WMNotification *WMRetainNotification(WMNotification *notification);
|
||||
|
||||
void *WMGetNotificationClientData(WMNotification *notification);
|
||||
|
||||
void *WMGetNotificationObject(WMNotification *notification);
|
||||
|
||||
char *WMGetNotificationName(WMNotification *notification);
|
||||
|
||||
|
||||
void WMAddNotificationObserver(WMNotificationObserverAction *observerAction,
|
||||
void *observer, char *name, void *object);
|
||||
|
||||
void WMPostNotification(WMNotification *notification);
|
||||
|
||||
void WMRemoveNotificationObserver(void *observer);
|
||||
|
||||
void WMRemoveNotificationObserverWithName(void *observer, char *name,
|
||||
void *object);
|
||||
|
||||
void WMPostNotificationName(char *name, void *object, void *clientData);
|
||||
|
||||
WMNotificationQueue *WMGetDefaultNotificationQueue(void);
|
||||
|
||||
WMNotificationQueue *WMCreateNotificationQueue(void);
|
||||
|
||||
void WMDequeueNotificationMatching(WMNotificationQueue *queue, unsigned mask);
|
||||
|
||||
void WMEnqueueNotification(WMNotificationQueue *queue, WMNotification *notification,
|
||||
WMPostingStyle postingStyle);
|
||||
|
||||
void WMEnqueueCoalesceNotification(WMNotificationQueue *queue,
|
||||
WMNotification *notification,
|
||||
WMPostingStyle postingStyle,
|
||||
unsigned coalesceMask);
|
||||
|
||||
|
||||
/*......................................................................*/
|
||||
|
||||
WMUserDefaults *WMGetStandardUserDefaults(void);
|
||||
|
||||
proplist_t WMGetUDObjectForKey(WMUserDefaults *database, char *defaultName);
|
||||
|
||||
void WMSetUDObjectForKey(WMUserDefaults *database, proplist_t object,
|
||||
char *defaultName);
|
||||
|
||||
void WMRemoveUDObjectForKey(WMUserDefaults *database, char *defaultName);
|
||||
|
||||
/* you can free the returned string */
|
||||
char *WMGetUDStringForKey(WMUserDefaults *database, char *defaultName);
|
||||
|
||||
int WMGetUDIntegerForKey(WMUserDefaults *database, char *defaultName);
|
||||
|
||||
int WMGetUDFloatForKey(WMUserDefaults *database, char *defaultName);
|
||||
|
||||
Bool WMGetUDBoolForKey(WMUserDefaults *database, char *defaultName);
|
||||
|
||||
void WMSetUDStringForKey(WMUserDefaults *database, char *value,
|
||||
char *defaultName);
|
||||
|
||||
void WMSetUDIntegerForKey(WMUserDefaults *database, int value,
|
||||
char *defaultName);
|
||||
|
||||
void WMSetUDFloatForKey(WMUserDefaults *database, float value,
|
||||
char *defaultName);
|
||||
|
||||
void WMSetUDBoolForKey(WMUserDefaults *database, Bool value,
|
||||
char *defaultName);
|
||||
|
||||
proplist_t WMGetUDSearchList(WMUserDefaults *database);
|
||||
|
||||
void WMSetUDSearchList(WMUserDefaults *database, proplist_t list);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
49
WINGs/configuration.c
Normal file
49
WINGs/configuration.c
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <proplist.h>
|
||||
|
||||
|
||||
_WINGsConfiguration WINGsConfiguration;
|
||||
|
||||
|
||||
|
||||
#define SYSTEM_FONT "-*-helvetica-medium-r-normal-*-%d-*-*-*-*-*-*-*"
|
||||
|
||||
#define BOLD_SYSTEM_FONT "-*-helvetica-bold-r-normal-*-%d-*-*-*-*-*-*-*"
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
W_ReadConfigurations(void)
|
||||
{
|
||||
WMUserDefaults *defaults;
|
||||
|
||||
memset(&WINGsConfiguration, 0, sizeof(_WINGsConfiguration));
|
||||
|
||||
defaults = WMGetStandardUserDefaults();
|
||||
|
||||
if (defaults) {
|
||||
WINGsConfiguration.systemFont =
|
||||
WMGetUDStringForKey(defaults, "SystemFont");
|
||||
|
||||
WINGsConfiguration.boldSystemFont =
|
||||
WMGetUDStringForKey(defaults, "BoldSystemFont");
|
||||
|
||||
WINGsConfiguration.doubleClickDelay =
|
||||
WMGetUDIntegerForKey(defaults, "DoubleClickTime");
|
||||
}
|
||||
|
||||
if (!WINGsConfiguration.systemFont) {
|
||||
WINGsConfiguration.systemFont = SYSTEM_FONT;
|
||||
}
|
||||
if (!WINGsConfiguration.boldSystemFont) {
|
||||
WINGsConfiguration.boldSystemFont = BOLD_SYSTEM_FONT;
|
||||
}
|
||||
if (WINGsConfiguration.doubleClickDelay == 0) {
|
||||
WINGsConfiguration.doubleClickDelay = 250;
|
||||
}
|
||||
}
|
||||
|
||||
118
WINGs/error.c
Normal file
118
WINGs/error.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* WindowMaker miscelaneous function library
|
||||
*
|
||||
* Copyright (c) 1997 Alfredo K. Kojima
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "../src/config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
extern char *_WINGS_progname;
|
||||
|
||||
#define MAXLINE 1024
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Prints a fatal error message with variable arguments and terminates
|
||||
*
|
||||
* msg - message to print with optional formatting
|
||||
* ... - arguments to use on formatting
|
||||
**************************************************************************/
|
||||
void
|
||||
wfatal(const char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[MAXLINE];
|
||||
|
||||
va_start(args, msg);
|
||||
|
||||
vsprintf(buf, msg, args);
|
||||
strcat(buf,"\n");
|
||||
fflush(stdout);
|
||||
fputs(_WINGS_progname, stderr);
|
||||
fputs(" fatal error: ",stderr);
|
||||
fputs(buf, stderr);
|
||||
fflush(NULL);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* Prints a warning message with variable arguments
|
||||
*
|
||||
* msg - message to print with optional formatting
|
||||
* ... - arguments to use on formatting
|
||||
*********************************************************************/
|
||||
void
|
||||
wwarning(const char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[MAXLINE];
|
||||
|
||||
va_start(args, msg);
|
||||
|
||||
vsprintf(buf, msg, args);
|
||||
strcat(buf,"\n");
|
||||
fflush(stdout);
|
||||
fputs(_WINGS_progname, stderr);
|
||||
fputs(" warning: ",stderr);
|
||||
fputs(buf, stderr);
|
||||
fflush(NULL);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* Prints a system error message with variable arguments
|
||||
*
|
||||
* msg - message to print with optional formatting
|
||||
* ... - arguments to use on formatting
|
||||
*********************************************************************/
|
||||
void
|
||||
wsyserror(const char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buf[MAXLINE];
|
||||
#ifdef HAVE_STRERROR
|
||||
int error=errno;
|
||||
#endif
|
||||
va_start(args, msg);
|
||||
vsprintf(buf, msg, args);
|
||||
fflush(stdout);
|
||||
fputs(_WINGS_progname, stderr);
|
||||
fputs(" error: ", stderr);
|
||||
strcat(buf, ": ");
|
||||
#ifdef HAVE_STRERROR
|
||||
strcat(buf, strerror(error));
|
||||
strcat(buf,"\n");
|
||||
fputs(buf, stderr);
|
||||
fflush(NULL);
|
||||
#else
|
||||
perror(buf);
|
||||
#endif
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
285
WINGs/findfile.c
Normal file
285
WINGs/findfile.c
Normal file
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* WindowMaker miscelaneous function library
|
||||
*
|
||||
* Copyright (c) 1997 Alfredo K. Kojima
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "../src/config.h"
|
||||
|
||||
#include "WUtil.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <pwd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
|
||||
char*
|
||||
wgethomedir()
|
||||
{
|
||||
char *home = getenv("HOME");
|
||||
struct passwd *user;
|
||||
|
||||
if (home)
|
||||
return home;
|
||||
|
||||
user = getpwuid(getuid());
|
||||
if (!user) {
|
||||
wsyserror("could not get password entry for UID %i", getuid());
|
||||
return "/";
|
||||
}
|
||||
if (!user->pw_dir) {
|
||||
return "/";
|
||||
} else {
|
||||
return user->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char*
|
||||
getuserhomedir(char *username)
|
||||
{
|
||||
struct passwd *user;
|
||||
|
||||
user = getpwnam(username);
|
||||
if (!user) {
|
||||
wsyserror("could not get password entry for user %s", username);
|
||||
return NULL;
|
||||
}
|
||||
if (!user->pw_dir) {
|
||||
return "/";
|
||||
} else {
|
||||
return user->pw_dir;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
char*
|
||||
wexpandpath(char *path)
|
||||
{
|
||||
char buffer2[PATH_MAX+2];
|
||||
char buffer[PATH_MAX+2];
|
||||
int i;
|
||||
|
||||
memset(buffer, 0, PATH_MAX+2);
|
||||
|
||||
if (*path=='~') {
|
||||
char *home;
|
||||
|
||||
path++;
|
||||
if (*path=='/' || *path==0) {
|
||||
home = wgethomedir();
|
||||
strcat(buffer, home);
|
||||
} else {
|
||||
int j;
|
||||
j = 0;
|
||||
while (*path!=0 && *path!='/') {
|
||||
buffer2[j++] = *path;
|
||||
buffer2[j] = 0;
|
||||
path++;
|
||||
}
|
||||
home = getuserhomedir(buffer2);
|
||||
if (!home)
|
||||
return NULL;
|
||||
strcat(buffer, home);
|
||||
}
|
||||
}
|
||||
|
||||
i = strlen(buffer);
|
||||
|
||||
while (*path!=0) {
|
||||
char *tmp;
|
||||
|
||||
if (*path=='$') {
|
||||
int j = 0;
|
||||
path++;
|
||||
/* expand $(HOME) or $HOME style environment variables */
|
||||
if (*path=='(') {
|
||||
path++;
|
||||
while (*path!=0 && *path!=')') {
|
||||
buffer2[j++] = *(path++);
|
||||
buffer2[j] = 0;
|
||||
}
|
||||
if (*path==')')
|
||||
path++;
|
||||
tmp = getenv(buffer2);
|
||||
if (!tmp) {
|
||||
buffer[i] = 0;
|
||||
strcat(buffer, "$(");
|
||||
strcat(buffer, buffer2);
|
||||
strcat(buffer, ")");
|
||||
i += strlen(buffer2)+3;
|
||||
} else {
|
||||
strcat(buffer, tmp);
|
||||
i += strlen(tmp);
|
||||
}
|
||||
} else {
|
||||
while (*path!=0 && *path!='/') {
|
||||
buffer2[j++] = *(path++);
|
||||
buffer2[j] = 0;
|
||||
}
|
||||
tmp = getenv(buffer2);
|
||||
if (!tmp) {
|
||||
strcat(buffer, "$");
|
||||
strcat(buffer, buffer2);
|
||||
i += strlen(buffer2)+1;
|
||||
} else {
|
||||
strcat(buffer, tmp);
|
||||
i += strlen(tmp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buffer[i++] = *path;
|
||||
path++;
|
||||
}
|
||||
}
|
||||
|
||||
return wstrdup(buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* findfile--
|
||||
* Finds a file in a : separated list of paths. ~ expansion is also
|
||||
* done.
|
||||
*
|
||||
* Returns:
|
||||
* The complete path for the file (in a newly allocated string) or
|
||||
* NULL if the file was not found.
|
||||
*
|
||||
* Side effects:
|
||||
* A new string is allocated. It must be freed later.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
char*
|
||||
wfindfile(char *paths, char *file)
|
||||
{
|
||||
char *path;
|
||||
char *tmp;
|
||||
int done;
|
||||
int len, flen;
|
||||
char *fullpath;
|
||||
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
if (*file=='/' || *file=='~' || *file=='$' || !paths) {
|
||||
if (access(file, R_OK)<0) {
|
||||
fullpath = wexpandpath(file);
|
||||
if (!fullpath)
|
||||
return NULL;
|
||||
|
||||
if (access(fullpath, R_OK)<0) {
|
||||
free(fullpath);
|
||||
return NULL;
|
||||
} else {
|
||||
return fullpath;
|
||||
}
|
||||
} else {
|
||||
return wstrdup(file);
|
||||
}
|
||||
}
|
||||
|
||||
flen = strlen(file);
|
||||
tmp = paths;
|
||||
done = 0;
|
||||
while (!done) {
|
||||
len = strcspn(tmp, ":");
|
||||
if (len==0) done=1;
|
||||
path = wmalloc(len+flen+2);
|
||||
path = memcpy(path, tmp, len);
|
||||
path[len]=0;
|
||||
strcat(path, "/");
|
||||
strcat(path, file);
|
||||
fullpath = wexpandpath(path);
|
||||
free(path);
|
||||
if (fullpath) {
|
||||
if (access(fullpath, R_OK)==0) {
|
||||
return fullpath;
|
||||
}
|
||||
free(fullpath);
|
||||
}
|
||||
tmp=&(tmp[len+1]);
|
||||
if (*tmp==0) break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
wfindfileinlist(char **path_list, char *file)
|
||||
{
|
||||
int i;
|
||||
char *path;
|
||||
int len, flen;
|
||||
char *fullpath;
|
||||
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
if (*file=='/' || *file=='~' || !path_list) {
|
||||
if (access(file, R_OK)<0) {
|
||||
fullpath = wexpandpath(file);
|
||||
if (!fullpath)
|
||||
return NULL;
|
||||
|
||||
if (access(fullpath, R_OK)<0) {
|
||||
free(fullpath);
|
||||
return NULL;
|
||||
} else {
|
||||
return fullpath;
|
||||
}
|
||||
} else {
|
||||
return wstrdup(file);
|
||||
}
|
||||
}
|
||||
|
||||
flen = strlen(file);
|
||||
for (i=0; path_list[i]!=NULL; i++) {
|
||||
len = strlen(path_list[i]);
|
||||
path = wmalloc(len+flen+2);
|
||||
path = memcpy(path, path_list[i], len);
|
||||
path[len]=0;
|
||||
strcat(path, "/");
|
||||
strcat(path, file);
|
||||
/* expand tilde */
|
||||
fullpath = wexpandpath(path);
|
||||
free(path);
|
||||
if (fullpath) {
|
||||
/* check if file is readable */
|
||||
if (access(fullpath, R_OK)==0) {
|
||||
return fullpath;
|
||||
}
|
||||
free(fullpath);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
104
WINGs/fontl.c
Normal file
104
WINGs/fontl.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* WINGs demo: font lister
|
||||
*
|
||||
* Copyright (c) 1998 Alfredo K. Kojima
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "WINGs.h"
|
||||
#include "WUtil.h"
|
||||
|
||||
void
|
||||
wAbort()
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void show(WMWidget *self, void *data)
|
||||
{
|
||||
char buf[60];
|
||||
void *d;
|
||||
WMLabel *l = (WMLabel*)data;
|
||||
d = WMGetHangedData(self);
|
||||
sprintf(buf, "%i - 0x%x - 0%o", (int)d, (int)d, (int)d);
|
||||
WMSetLabelText(l, buf);
|
||||
}
|
||||
|
||||
void quit(WMWidget *self, void *data)
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
Display *dpy;
|
||||
WMWindow *win;
|
||||
WMScreen *scr;
|
||||
WMButton *lab, *l0=NULL;
|
||||
WMLabel *pos;
|
||||
int x, y, c;
|
||||
char buf[20];
|
||||
|
||||
WMInitializeApplication("FontView", &argc, argv);
|
||||
|
||||
dpy = XOpenDisplay("");
|
||||
if (!dpy) {
|
||||
wfatal("cant open display");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
scr = WMCreateSimpleApplicationScreen(dpy);
|
||||
|
||||
win = WMCreateWindow(scr, "main");
|
||||
WMResizeWidget(win, 20*33, 20+20*9);
|
||||
WMSetWindowTitle(win, "Font Chars");
|
||||
WMSetWindowCloseAction(win, quit, NULL);
|
||||
pos = WMCreateLabel(win);
|
||||
WMResizeWidget(pos, 20*33, 20);
|
||||
WMMoveWidget(pos, 10, 5);
|
||||
|
||||
c = 0;
|
||||
for (y=0; y<8; y++) {
|
||||
for (x=0; x<32; x++, c++) {
|
||||
lab = WMCreateCustomButton(win, WBBStateLightMask);
|
||||
WMResizeWidget(lab, 20, 20);
|
||||
WMMoveWidget(lab, 10+x*20, 30+y*20);
|
||||
sprintf(buf, "%c", c);
|
||||
WMSetButtonText(lab, buf);
|
||||
WMSetButtonAction(lab, show, pos);
|
||||
WMHangData(lab, (void*)c);
|
||||
if (c>0) {
|
||||
WMGroupButtons(l0, lab);
|
||||
} else {
|
||||
l0 = lab;
|
||||
}
|
||||
}
|
||||
}
|
||||
WMRealizeWidget(win);
|
||||
WMMapSubwidgets(win);
|
||||
WMMapWidget(win);
|
||||
WMScreenMainLoop(scr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
406
WINGs/hashtable.c
Normal file
406
WINGs/hashtable.c
Normal file
@@ -0,0 +1,406 @@
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "WUtil.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#define INITIAL_CAPACITY 23
|
||||
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
# define INLINE inline
|
||||
#else
|
||||
# define INLINE
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct HashItem {
|
||||
void *key;
|
||||
void *data;
|
||||
|
||||
struct HashItem *next; /* collided item list */
|
||||
} HashItem;
|
||||
|
||||
|
||||
typedef struct W_HashTable {
|
||||
WMHashTableCallbacks callbacks;
|
||||
|
||||
unsigned itemCount;
|
||||
unsigned size; /* table size */
|
||||
|
||||
HashItem **table;
|
||||
} HashTable;
|
||||
|
||||
|
||||
|
||||
|
||||
#define HASH(table, key) (((table)->callbacks.hash ? \
|
||||
(*(table)->callbacks.hash)(key) : hashPtr(key)) % (table)->size)
|
||||
|
||||
#define DUPKEY(table, key) ((table)->callbacks.retainKey ? \
|
||||
(*(table)->callbacks.retainKey)(key) : (key))
|
||||
|
||||
#define RELKEY(table, key) if ((table)->callbacks.releaseKey) \
|
||||
(*(table)->callbacks.releaseKey)(key)
|
||||
|
||||
|
||||
|
||||
|
||||
static INLINE unsigned
|
||||
hashString(const char *key)
|
||||
{
|
||||
unsigned ret = 0;
|
||||
unsigned ctr = 0;
|
||||
|
||||
while (*key) {
|
||||
ret ^= *(char*)key++ << ctr;
|
||||
ctr = (ctr + 1) % sizeof (char *);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static INLINE unsigned
|
||||
hashPtr(const void *key)
|
||||
{
|
||||
return ((size_t)key / sizeof(char*));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
rellocateItem(WMHashTable *table, HashItem *item)
|
||||
{
|
||||
unsigned h;
|
||||
|
||||
h = HASH(table, item->key);
|
||||
|
||||
item->next = table->table[h];
|
||||
table->table[h] = item;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rebuildTable(WMHashTable *table)
|
||||
{
|
||||
HashItem *next;
|
||||
HashItem **oldArray;
|
||||
int i;
|
||||
int oldSize;
|
||||
int newSize;
|
||||
|
||||
oldArray = table->table;
|
||||
oldSize = table->size;
|
||||
|
||||
newSize = table->size*2;
|
||||
|
||||
table->table = wmalloc(sizeof(char*)*newSize);
|
||||
memset(table->table, 0, sizeof(char*)*newSize);
|
||||
table->size = newSize;
|
||||
|
||||
for (i = 0; i < oldSize; i++) {
|
||||
while (oldArray[i]!=NULL) {
|
||||
next = oldArray[i]->next;
|
||||
rellocateItem(table, oldArray[i]);
|
||||
oldArray[i] = next;
|
||||
}
|
||||
}
|
||||
free(oldArray);
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMHashTable*
|
||||
WMCreateHashTable(WMHashTableCallbacks callbacks)
|
||||
{
|
||||
HashTable *table;
|
||||
|
||||
table = wmalloc(sizeof(HashTable));
|
||||
memset(table, 0, sizeof(HashTable));
|
||||
|
||||
table->callbacks = callbacks;
|
||||
|
||||
table->size = INITIAL_CAPACITY;
|
||||
|
||||
table->table = wmalloc(sizeof(HashItem*)*table->size);
|
||||
memset(table->table, 0, sizeof(HashItem*)*table->size);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMResetHashTable(WMHashTable *table)
|
||||
{
|
||||
HashItem *item, *tmp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < table->size; i++) {
|
||||
item = table->table[i];
|
||||
while (item) {
|
||||
tmp = item->next;
|
||||
RELKEY(table, item);
|
||||
free(item);
|
||||
item = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
table->itemCount = 0;
|
||||
|
||||
if (table->size > INITIAL_CAPACITY) {
|
||||
free(table->table);
|
||||
table->size = INITIAL_CAPACITY;
|
||||
table->table = wmalloc(sizeof(HashItem*)*table->size);
|
||||
}
|
||||
memset(table->table, 0, sizeof(HashItem*)*table->size);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMFreeHashTable(WMHashTable *table)
|
||||
{
|
||||
HashItem *item, *tmp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < table->size; i++) {
|
||||
item = table->table[i];
|
||||
while (item) {
|
||||
tmp = item->next;
|
||||
RELKEY(table, item);
|
||||
free(item);
|
||||
item = tmp;
|
||||
}
|
||||
}
|
||||
free(table->table);
|
||||
free(table);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void*
|
||||
WMHashGet(WMHashTable *table, const void *key)
|
||||
{
|
||||
unsigned h;
|
||||
HashItem *item;
|
||||
|
||||
h = HASH(table, key);
|
||||
item = table->table[h];
|
||||
|
||||
if (table->callbacks.keyIsEqual) {
|
||||
while (item) {
|
||||
if ((*table->callbacks.keyIsEqual)(key, item->key)) {
|
||||
break;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
} else {
|
||||
while (item) {
|
||||
if (key == item->key) {
|
||||
break;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
if (item)
|
||||
return item->data;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void*
|
||||
WMHashInsert(WMHashTable *table, void *key, void *data)
|
||||
{
|
||||
unsigned h;
|
||||
HashItem *item;
|
||||
int replacing = 0;
|
||||
|
||||
h = HASH(table, key);
|
||||
/* look for the entry */
|
||||
item = table->table[h];
|
||||
if (table->callbacks.keyIsEqual) {
|
||||
while (item) {
|
||||
if ((*table->callbacks.keyIsEqual)(key, item->key)) {
|
||||
replacing = 1;
|
||||
break;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
} else {
|
||||
while (item) {
|
||||
if (key == item->key) {
|
||||
replacing = 1;
|
||||
break;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (replacing) {
|
||||
void *old;
|
||||
|
||||
old = item->data;
|
||||
item->data = data;
|
||||
RELKEY(table, item->key);
|
||||
item->key = DUPKEY(table, key);
|
||||
|
||||
return old;
|
||||
} else {
|
||||
HashItem *nitem;
|
||||
|
||||
nitem = wmalloc(sizeof(HashItem));
|
||||
nitem->key = DUPKEY(table, key);
|
||||
nitem->data = data;
|
||||
nitem->next = table->table[h];
|
||||
table->table[h] = nitem;
|
||||
|
||||
table->itemCount++;
|
||||
}
|
||||
|
||||
/* OPTIMIZE: put this in an idle handler.*/
|
||||
if (table->itemCount > table->size) {
|
||||
#ifdef DEBUG0
|
||||
printf("rebuilding hash table...\n");
|
||||
#endif
|
||||
rebuildTable(table);
|
||||
#ifdef DEBUG0
|
||||
printf("finished rebuild.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static HashItem*
|
||||
deleteFromList(HashTable *table, HashItem *item, const void *key)
|
||||
{
|
||||
HashItem *next;
|
||||
|
||||
if (item==NULL)
|
||||
return NULL;
|
||||
|
||||
if ((table->callbacks.keyIsEqual
|
||||
&& (*table->callbacks.keyIsEqual)(key, item->key))
|
||||
|| (!table->callbacks.keyIsEqual && key==item->key)) {
|
||||
|
||||
next = item->next;
|
||||
RELKEY(table, item->key);
|
||||
free(item);
|
||||
|
||||
table->itemCount--;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
item->next = deleteFromList(table, item->next, key);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMHashRemove(WMHashTable *table, const void *key)
|
||||
{
|
||||
unsigned h;
|
||||
|
||||
h = HASH(table, key);
|
||||
|
||||
table->table[h] = deleteFromList(table, table->table[h], key);
|
||||
}
|
||||
|
||||
|
||||
WMHashEnumerator
|
||||
WMEnumerateHashTable(WMHashTable *table)
|
||||
{
|
||||
WMHashEnumerator enumerator;
|
||||
|
||||
enumerator.table = table;
|
||||
enumerator.index = 0;
|
||||
enumerator.nextItem = table->table[0];
|
||||
|
||||
return enumerator;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void*
|
||||
WMNextHashEnumeratorItem(WMHashEnumerator *enumerator)
|
||||
{
|
||||
void *data = NULL;
|
||||
|
||||
/* this assumes the table doesn't change between
|
||||
* WMEnumerateHashTable() and WMNextHashEnumeratorItem() calls */
|
||||
|
||||
if (enumerator->nextItem==NULL) {
|
||||
HashTable *table = enumerator->table;
|
||||
while (++enumerator->index < table->size) {
|
||||
if (table->table[enumerator->index]!=NULL) {
|
||||
enumerator->nextItem = table->table[enumerator->index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enumerator->nextItem) {
|
||||
data = ((HashItem*)enumerator->nextItem)->data;
|
||||
enumerator->nextItem = ((HashItem*)enumerator->nextItem)->next;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
unsigned
|
||||
WMCountHashTable(WMHashTable *table)
|
||||
{
|
||||
return table->itemCount;
|
||||
}
|
||||
|
||||
|
||||
static Bool
|
||||
compareStrings(const char *key1, const char *key2)
|
||||
{
|
||||
return strcmp(key1, key2)==0;
|
||||
}
|
||||
|
||||
|
||||
typedef unsigned (*hashFunc)(const void*);
|
||||
typedef Bool (*isEqualFunc)(const void*, const void*);
|
||||
typedef void* (*retainFunc)(const void*);
|
||||
typedef void (*releaseFunc)(const void*);
|
||||
|
||||
|
||||
const WMHashTableCallbacks WMIntHashCallbacks = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const WMHashTableCallbacks WMStringHashCallbacks = {
|
||||
(hashFunc)hashString,
|
||||
(isEqualFunc)compareStrings,
|
||||
(retainFunc)wstrdup,
|
||||
(releaseFunc)free
|
||||
};
|
||||
|
||||
|
||||
|
||||
const WMHashTableCallbacks WMStringPointerHashCallbacks = {
|
||||
(hashFunc)hashString,
|
||||
(isEqualFunc)compareStrings,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
12
WINGs/international.c
Normal file
12
WINGs/international.c
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
void
|
||||
InitI18n(Display *dpy)
|
||||
{
|
||||
|
||||
}
|
||||
56
WINGs/logo.xpm
Normal file
56
WINGs/logo.xpm
Normal file
@@ -0,0 +1,56 @@
|
||||
/* XPM */
|
||||
static char * GNUSTEP_XPM[] = {
|
||||
"45 45 8 1",
|
||||
" c None",
|
||||
". c #666666666666",
|
||||
"X c #777777777777",
|
||||
"o c #596559656185",
|
||||
"O c #000000000000",
|
||||
"+ c #3CF33CF33CF3",
|
||||
"@ c #CF3CCF3CCF3C",
|
||||
"# c #FFFFFFFFFFFF",
|
||||
" ",
|
||||
" .Xooooooooo. ",
|
||||
" ..ooOOOOOOOOOOOOOo. ",
|
||||
" .XoOOOOOOOOOOOOOOOOOO+ ",
|
||||
" .oOOOOOOOOOOOOOOOOOOOOOO+ ",
|
||||
" XOOOOOOOOOOOOOOOOOOOOOOOOOOo ",
|
||||
" oOOOOOOOOOOOOOOOOOOOOOOOOOOOO+ ",
|
||||
" oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO+ooooooo",
|
||||
" +OOOOOOOOOOOOOOOOOOOOOOOOoXXXXX.XOOOOOOO",
|
||||
" XOOOOOOOOOOOOOOOOOOOOOOOOOX#######.OOOOOO",
|
||||
" XOOOOOOOOOOOOOOOOOOOOOOOOOOX########oOOOOO",
|
||||
" OOOOOOOOOOOOOOOOOOOOOOOOOOOX#########oOOOO",
|
||||
" oOOOOOOOOOOOOOOOOOOOOOOOOOOOX#########@OOOO",
|
||||
" OOOOOOOOOOOOOOOOOOOOOOOOOOOOX##########oOOO",
|
||||
" oOOOOOOOOOOOOOOOOOOOOOOOOOOOOX##########@OOO",
|
||||
" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOX###########+OO",
|
||||
" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOX###########oOO",
|
||||
"oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX###########@OO",
|
||||
"+OOOOOOOOOOOOOOOOOOOOOOOOOOOOOX###########@OO",
|
||||
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX############XO",
|
||||
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX############XO",
|
||||
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX############XO",
|
||||
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOX############XO",
|
||||
"OOOOOOOOOOOOOOOoX.X.X.X.XX.XXX@############XO",
|
||||
"OOOOOOOOOOOOOOOX###########################XO",
|
||||
"OOOOOOOOOOOOOOOX###########################XO",
|
||||
"OOOOOOOOOOOOOOOX###########################XO",
|
||||
"+OOOOOOOOOOOOOOX###########################OO",
|
||||
"oOOOOOOOOOOOOOOX###########################OO",
|
||||
" OOOOOOOOOOOOOOX##########################XOO",
|
||||
" OOOOOOOOOOOOOOX##########################oOO",
|
||||
" oOOOOOOOOOOOOOX#########################@OOO",
|
||||
" OOOOOOOOOOOOOX#########################+OOO",
|
||||
" oOOOOOOOOOOOOX########################@OOOO",
|
||||
" OOOOOOOOOOOOX########################oOOOO",
|
||||
" OOOOOOOOOOOX#######################oOOOOO",
|
||||
" OOOOOOOOOOX######################XOOOOOO",
|
||||
"OOOOOOOXXXXXXXX@#####################@OOOOOOO",
|
||||
"OOOOOOOo############################@OOOOOOOO",
|
||||
"OOOOOOOOO@#########################oOOOOOOOOO",
|
||||
"OOOOOOOOOOX######################@oOOOOOOOOOO",
|
||||
"OOOOOOOOOOOOX###################XOOOOOOOOOOOO",
|
||||
"OOOOOOOOOOOOOOX@#############@XOOOOOOOOOOOOOO",
|
||||
"OOOOOOOOOOOOOOOOOXXX#####XXXOOOOOOOOOOOOOOOOO",
|
||||
"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO"};
|
||||
169
WINGs/memory.c
Normal file
169
WINGs/memory.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* WindowMaker miscelaneous function library
|
||||
*
|
||||
* Copyright (c) 1997 Alfredo K. Kojima
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "../src/config.h"
|
||||
|
||||
#include "WUtil.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef False
|
||||
# define False 0
|
||||
#endif
|
||||
#ifndef True
|
||||
# define True 1
|
||||
#endif
|
||||
|
||||
extern void wAbort(int);
|
||||
|
||||
static int Aborting=0; /* if we're in the middle of an emergency exit */
|
||||
|
||||
|
||||
static WMHashTable *table = NULL;
|
||||
|
||||
|
||||
void *wmalloc(size_t size)
|
||||
{
|
||||
void *tmp;
|
||||
|
||||
tmp = malloc(size);
|
||||
if (tmp == NULL) {
|
||||
wwarning("malloc() failed. Retrying after 2s.");
|
||||
sleep(2);
|
||||
tmp = malloc(size);
|
||||
if (tmp == NULL) {
|
||||
if (Aborting) {
|
||||
puts("Real Bad Error: recursive malloc() failure.");
|
||||
exit(-1);
|
||||
} else {
|
||||
wfatal("virtual memory exhausted");
|
||||
Aborting=1;
|
||||
wAbort(False);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
void *wrealloc(void *ptr, size_t newsize)
|
||||
{
|
||||
void *nptr;
|
||||
|
||||
if (!ptr) {
|
||||
nptr = malloc(newsize);
|
||||
} else {
|
||||
nptr=realloc(ptr, newsize);
|
||||
}
|
||||
if (nptr==NULL) {
|
||||
printf("Could not do realloc");
|
||||
return NULL;
|
||||
}
|
||||
return nptr;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
wretain(void *ptr)
|
||||
{
|
||||
int *refcount;
|
||||
|
||||
if (!table) {
|
||||
table = WMCreateHashTable(WMIntHashCallbacks);
|
||||
}
|
||||
|
||||
refcount = WMHashGet(table, ptr);
|
||||
if (!refcount) {
|
||||
refcount = wmalloc(sizeof(int));
|
||||
*refcount = 1;
|
||||
WMHashInsert(table, ptr, refcount);
|
||||
#ifdef VERBOSE
|
||||
printf("== %i (%p)\n", *refcount, ptr);
|
||||
#endif
|
||||
} else {
|
||||
(*refcount)++;
|
||||
#ifdef VERBOSE
|
||||
printf("+ %i (%p)\n", *refcount, ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wrelease(void *ptr)
|
||||
{
|
||||
int *refcount;
|
||||
|
||||
refcount = WMHashGet(table, ptr);
|
||||
if (!refcount) {
|
||||
wwarning("trying to release unexisting data %p", ptr);
|
||||
} else {
|
||||
(*refcount)--;
|
||||
if (*refcount < 1) {
|
||||
#ifdef VERBOSE
|
||||
printf("RELEASING %p\n", ptr);
|
||||
#endif
|
||||
WMHashRemove(table, ptr);
|
||||
free(refcount);
|
||||
free(ptr);
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
else {
|
||||
printf("- %i (%p)\n", *refcount, ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
wstrdup(char *str)
|
||||
{
|
||||
assert(str!=NULL);
|
||||
|
||||
return strcpy(wmalloc(strlen(str)+1), str);
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
wstrappend(char *dst, char *src)
|
||||
{
|
||||
char *str;
|
||||
|
||||
if (!dst)
|
||||
return wstrdup(src);
|
||||
else if (!src)
|
||||
return wstrdup(dst);
|
||||
|
||||
str = wmalloc(strlen(dst)+strlen(src)+1);
|
||||
strcpy(str, dst);
|
||||
strcat(str, src);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
221
WINGs/mywidget.c
Normal file
221
WINGs/mywidget.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Demo user widget for WINGs.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1998 Alfredo K. Kojima
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Include the WINGs private data header.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include "WINGsP.h"
|
||||
|
||||
/*
|
||||
* Our public header.
|
||||
*/
|
||||
#include "mywidget.h"
|
||||
|
||||
/*
|
||||
* Define the widget "class"
|
||||
*/
|
||||
typedef struct W_MyWidget {
|
||||
/* these two fields must be present in all your widgets in this
|
||||
* exact position */
|
||||
W_Class widgetClass;
|
||||
WMView *view;
|
||||
|
||||
/* put your stuff here */
|
||||
char *text;
|
||||
|
||||
} _MyWidget;
|
||||
|
||||
|
||||
|
||||
|
||||
/* some forward declarations */
|
||||
|
||||
static void destroyMyWidget(_MyWidget *mPtr);
|
||||
static void paintMyWidget(_MyWidget *mPtr);
|
||||
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleActionEvents(XEvent *event, void *data);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Some procedures you might want to override. Don't forget to call
|
||||
* the equivalent view procedure after (or before) doing your stuff.
|
||||
* See the source for the other widgets to see how to use.
|
||||
* You won't need to use this most of the time.
|
||||
*/
|
||||
static W_ViewProcedureTable _MyWidgetViewProcedures = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/* our widget class ID */
|
||||
static W_Class myWidgetClass = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Initializer for our widget. Must be called before creating any
|
||||
* instances of the widget.
|
||||
*/
|
||||
W_Class
|
||||
InitMyWidget(WMScreen *scr)
|
||||
{
|
||||
/* register our widget with WINGs and get our widget class ID */
|
||||
if (!myWidgetClass) {
|
||||
myWidgetClass = W_RegisterUserWidget(&_MyWidgetViewProcedures);
|
||||
}
|
||||
|
||||
return myWidgetClass;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Our widget fabrication plant.
|
||||
*/
|
||||
MyWidget*
|
||||
CreateMyWidget(WMWidget *parent)
|
||||
{
|
||||
MyWidget *mPtr;
|
||||
|
||||
/* allocate some storage for our new widget instance */
|
||||
mPtr = wmalloc(sizeof(MyWidget));
|
||||
/* initialize it */
|
||||
memset(mPtr, 0, sizeof(MyWidget));
|
||||
|
||||
/* set the class ID */
|
||||
mPtr->widgetClass = myWidgetClass;
|
||||
|
||||
/*
|
||||
* Create the view for our widget.
|
||||
* Note: the Window for the view is only created after the view is
|
||||
* realized with W_RealizeView()
|
||||
*
|
||||
* Consider the returned view as read-only.
|
||||
*/
|
||||
mPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!mPtr->view) {
|
||||
free(mPtr);
|
||||
return NULL;
|
||||
}
|
||||
/* always do this */
|
||||
mPtr->view->self = mPtr;
|
||||
|
||||
/*
|
||||
* Intercept some events for our widget, so that we can handle them.
|
||||
*/
|
||||
WMCreateEventHandler(mPtr->view, ExposureMask /* this allows us to know when we should paint */
|
||||
|StructureNotifyMask, /* this allows us to know things like when we are destroyed */
|
||||
handleEvents, mPtr);
|
||||
|
||||
/*
|
||||
* Intercept some other events. This could be merged with the above
|
||||
* call, but we separate for more organization.
|
||||
*/
|
||||
WMCreateEventHandler(mPtr->view, ButtonPressMask,handleActionEvents, mPtr);
|
||||
|
||||
return mPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Paint our widget contents.
|
||||
*/
|
||||
static void
|
||||
paintMyWidget(_MyWidget *mPtr)
|
||||
{
|
||||
W_Screen *scr = mPtr->view->screen;
|
||||
WMColor *color;
|
||||
|
||||
|
||||
if (mPtr->text) {
|
||||
|
||||
color = WMWhiteColor(scr);
|
||||
|
||||
W_PaintText(mPtr->view, mPtr->view->window, scr->normalFont, 0, 0,
|
||||
mPtr->view->size.width, WACenter, W_GC(color),
|
||||
False, mPtr->text, strlen(mPtr->text));
|
||||
|
||||
WMReleaseColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
_MyWidget *mPtr = (_MyWidget*)data;
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintMyWidget(mPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyMyWidget(mPtr);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
_MyWidget *mPtr = (_MyWidget*)data;
|
||||
|
||||
switch (event->type) {
|
||||
case ButtonPress:
|
||||
XBell(mPtr->view->screen->display, 100);
|
||||
XBell(mPtr->view->screen->display, 100);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SetMyWidgetText(MyWidget *mPtr, char *text)
|
||||
{
|
||||
CHECK_CLASS(mPtr, myWidgetClass);
|
||||
|
||||
if (mPtr->text)
|
||||
free(mPtr->text);
|
||||
|
||||
mPtr->text = wstrdup(text);
|
||||
|
||||
if (W_VIEW_MAPPED(mPtr->view)) {
|
||||
paintMyWidget(mPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroyMyWidget(_MyWidget *mPtr)
|
||||
{
|
||||
/*
|
||||
* Free all data we allocated for our widget.
|
||||
*/
|
||||
|
||||
if (mPtr->text)
|
||||
free(mPtr->text);
|
||||
|
||||
free(mPtr);
|
||||
}
|
||||
|
||||
|
||||
15
WINGs/mywidget.h
Normal file
15
WINGs/mywidget.h
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
/*
|
||||
* Header foy demo widget.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct W_MyWidget MyWidget;
|
||||
|
||||
|
||||
MyWidget *CreateMyWidget(WMWidget *parent);
|
||||
|
||||
void SetMyWidgetText(MyWidget *mPtr, char *text);
|
||||
|
||||
W_Class InitMyWidget(WMScreen *scr);
|
||||
|
||||
414
WINGs/notification.c
Normal file
414
WINGs/notification.c
Normal file
@@ -0,0 +1,414 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "WUtil.h"
|
||||
|
||||
|
||||
typedef struct W_Notification {
|
||||
char *name;
|
||||
void *object;
|
||||
void *clientData;
|
||||
int refCount;
|
||||
} Notification;
|
||||
|
||||
|
||||
|
||||
char*
|
||||
WMGetNotificationName(WMNotification *notification)
|
||||
{
|
||||
return notification->name;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
WMGetNotificationObject(WMNotification *notification)
|
||||
{
|
||||
return notification->object;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
WMGetNotificationClientData(WMNotification *notification)
|
||||
{
|
||||
return notification->clientData;
|
||||
}
|
||||
|
||||
|
||||
WMNotification*
|
||||
WMCreateNotification(char *name, void *object, void *clientData)
|
||||
{
|
||||
Notification *nPtr;
|
||||
|
||||
nPtr = wmalloc(sizeof(Notification));
|
||||
|
||||
nPtr->name = name;
|
||||
nPtr->object = object;
|
||||
nPtr->clientData = clientData;
|
||||
|
||||
nPtr->refCount = 1;
|
||||
|
||||
return nPtr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMReleaseNotification(WMNotification *notification)
|
||||
{
|
||||
notification->refCount--;
|
||||
|
||||
if (notification->refCount < 1) {
|
||||
free(notification);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMNotification*
|
||||
WMRetainNotification(WMNotification *notification)
|
||||
{
|
||||
notification->refCount++;
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
|
||||
/***************** Notification Center *****************/
|
||||
|
||||
typedef struct NotificationObserver {
|
||||
WMNotificationObserverAction *observerAction;
|
||||
void *observer;
|
||||
|
||||
char *name;
|
||||
void *object;
|
||||
|
||||
struct NotificationObserver *prev; /* for tables */
|
||||
struct NotificationObserver *next;
|
||||
struct NotificationObserver *nextAction; /* for observerTable */
|
||||
} NotificationObserver;
|
||||
|
||||
|
||||
typedef struct W_NotificationCenter {
|
||||
WMHashTable *nameTable; /* names -> observer lists */
|
||||
WMHashTable *objectTable; /* object -> observer lists */
|
||||
NotificationObserver *nilList; /* obervers that catch everything */
|
||||
|
||||
WMHashTable *observerTable; /* observer -> NotificationObserver */
|
||||
} NotificationCenter;
|
||||
|
||||
|
||||
/* default (and only) center */
|
||||
static NotificationCenter *notificationCenter = NULL;
|
||||
|
||||
|
||||
void
|
||||
W_InitNotificationCenter(void)
|
||||
{
|
||||
notificationCenter = wmalloc(sizeof(NotificationCenter));
|
||||
|
||||
notificationCenter->nameTable = WMCreateHashTable(WMStringPointerHashCallbacks);
|
||||
notificationCenter->objectTable = WMCreateHashTable(WMIntHashCallbacks);
|
||||
notificationCenter->nilList = NULL;
|
||||
|
||||
notificationCenter->observerTable = WMCreateHashTable(WMIntHashCallbacks);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMAddNotificationObserver(WMNotificationObserverAction *observerAction,
|
||||
void *observer, char *name, void *object)
|
||||
{
|
||||
NotificationObserver *oRec, *rec;
|
||||
|
||||
oRec = wmalloc(sizeof(NotificationObserver));
|
||||
oRec->observerAction = observerAction;
|
||||
oRec->observer = observer;
|
||||
oRec->name = name;
|
||||
oRec->object = object;
|
||||
oRec->next = NULL;
|
||||
oRec->prev = NULL;
|
||||
|
||||
|
||||
/* put this action in the list of actions for this observer */
|
||||
rec = WMHashInsert(notificationCenter->observerTable, observer, oRec);
|
||||
|
||||
if (rec) {
|
||||
/* if this is not the first action for the observer */
|
||||
oRec->nextAction = rec;
|
||||
} else {
|
||||
oRec->nextAction = NULL;
|
||||
}
|
||||
|
||||
if (!name && !object) {
|
||||
/* catch-all */
|
||||
oRec->next = notificationCenter->nilList;
|
||||
if (notificationCenter->nilList) {
|
||||
notificationCenter->nilList->prev = oRec;
|
||||
}
|
||||
notificationCenter->nilList = oRec;
|
||||
} else if (!name) {
|
||||
/* any message coming from object */
|
||||
rec = WMHashInsert(notificationCenter->objectTable, object, oRec);
|
||||
oRec->next = rec;
|
||||
if (rec) {
|
||||
rec->prev = oRec;
|
||||
}
|
||||
} else {
|
||||
/* name && (object || !object) */
|
||||
rec = WMHashInsert(notificationCenter->nameTable, name, oRec);
|
||||
oRec->next = rec;
|
||||
if (rec) {
|
||||
rec->prev = oRec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMPostNotification(WMNotification *notification)
|
||||
{
|
||||
NotificationObserver *orec, *tmp;
|
||||
|
||||
WMRetainNotification(notification);
|
||||
|
||||
/* tell the observers that want to know about a particular message */
|
||||
orec = WMHashGet(notificationCenter->nameTable, notification->name);
|
||||
|
||||
while (orec) {
|
||||
tmp = orec->next;
|
||||
|
||||
if (!orec->object || orec->object == notification->object) {
|
||||
/* tell the observer */
|
||||
if (orec->observerAction) {
|
||||
(*orec->observerAction)(orec->observer, notification);
|
||||
}
|
||||
}
|
||||
|
||||
orec = tmp;
|
||||
}
|
||||
|
||||
/* tell the observers that want to know about an object */
|
||||
orec = WMHashGet(notificationCenter->objectTable, notification->object);
|
||||
|
||||
while (orec) {
|
||||
tmp = orec->next;
|
||||
|
||||
/* tell the observer */
|
||||
if (orec->observerAction) {
|
||||
(*orec->observerAction)(orec->observer, notification);
|
||||
}
|
||||
orec = tmp;
|
||||
}
|
||||
|
||||
/* tell the catch all observers */
|
||||
orec = notificationCenter->nilList;
|
||||
while (orec) {
|
||||
tmp = orec->next;
|
||||
|
||||
/* tell the observer */
|
||||
if (orec->observerAction) {
|
||||
(*orec->observerAction)(orec->observer, notification);
|
||||
}
|
||||
orec = tmp;
|
||||
}
|
||||
|
||||
WMReleaseNotification(notification);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMRemoveNotificationObserver(void *observer)
|
||||
{
|
||||
NotificationObserver *orec, *tmp, *rec;
|
||||
|
||||
|
||||
/* get the list of actions the observer is doing */
|
||||
orec = WMHashGet(notificationCenter->observerTable, observer);
|
||||
|
||||
/*
|
||||
* FOREACH orec IN actionlist for observer
|
||||
* DO
|
||||
* remove from respective lists/tables
|
||||
* free
|
||||
* END
|
||||
*/
|
||||
while (orec) {
|
||||
tmp = orec->nextAction;
|
||||
|
||||
if (!orec->name && !orec->object) {
|
||||
/* catch-all */
|
||||
if (notificationCenter->nilList==orec)
|
||||
notificationCenter->nilList = orec->next;
|
||||
} else if (!orec->name) {
|
||||
/* any message coming from object */
|
||||
rec = WMHashGet(notificationCenter->objectTable, orec->object);
|
||||
if (rec==orec) {
|
||||
/* replace table entry */
|
||||
if (orec->next) {
|
||||
WMHashInsert(notificationCenter->objectTable, orec->object,
|
||||
orec->next);
|
||||
} else {
|
||||
WMHashRemove(notificationCenter->objectTable, orec->object);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* name && (object || !object) */
|
||||
rec = WMHashGet(notificationCenter->nameTable, orec->name);
|
||||
if (rec==orec) {
|
||||
/* replace table entry */
|
||||
if (orec->next) {
|
||||
WMHashInsert(notificationCenter->nameTable, orec->name,
|
||||
orec->next);
|
||||
} else {
|
||||
WMHashRemove(notificationCenter->nameTable, orec->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (orec->prev)
|
||||
orec->prev->next = orec->next;
|
||||
if (orec->next)
|
||||
orec->next->prev = orec->prev;
|
||||
|
||||
free(orec);
|
||||
|
||||
orec = tmp;
|
||||
}
|
||||
|
||||
WMHashRemove(notificationCenter->observerTable, observer);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMRemoveNotificationObserverWithName(void *observer, char *name, void *object)
|
||||
{
|
||||
NotificationObserver *orec, *tmp, *rec;
|
||||
|
||||
/* get the list of actions the observer is doing */
|
||||
orec = WMHashGet(notificationCenter->observerTable, observer);
|
||||
|
||||
while (orec) {
|
||||
tmp = orec->nextAction;
|
||||
if (orec->name == name && orec->object == object) {
|
||||
if (!name && !object) {
|
||||
if (notificationCenter->nilList == orec)
|
||||
notificationCenter->nilList = orec->next;
|
||||
} else if (!name) {
|
||||
rec = WMHashGet(notificationCenter->objectTable, orec->object);
|
||||
if (rec==orec) {
|
||||
assert(rec->prev==NULL);
|
||||
/* replace table entry */
|
||||
if (orec->next) {
|
||||
WMHashInsert(notificationCenter->objectTable, orec->object,
|
||||
orec->next);
|
||||
} else {
|
||||
WMHashRemove(notificationCenter->objectTable,
|
||||
orec->object);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rec = WMHashGet(notificationCenter->nameTable, orec->name);
|
||||
if (rec==orec) {
|
||||
assert(rec->prev==NULL);
|
||||
/* replace table entry */
|
||||
if (orec->next) {
|
||||
WMHashInsert(notificationCenter->nameTable, orec->name,
|
||||
orec->next);
|
||||
} else {
|
||||
WMHashRemove(notificationCenter->nameTable, orec->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* update the action list for the observer */
|
||||
rec = WMHashGet(notificationCenter->observerTable, observer);
|
||||
|
||||
if (rec == orec) {
|
||||
if (orec->nextAction) {
|
||||
WMHashInsert(notificationCenter->nameTable, observer,
|
||||
orec->nextAction);
|
||||
} else {
|
||||
WMHashRemove(notificationCenter->nameTable, observer);
|
||||
}
|
||||
}
|
||||
|
||||
if (orec->prev)
|
||||
orec->prev->next = orec->next;
|
||||
if (orec->next)
|
||||
orec->next->prev = orec->prev;
|
||||
free(orec);
|
||||
}
|
||||
orec = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMPostNotificationName(char *name, void *object, void *clientData)
|
||||
{
|
||||
WMNotification *notification;
|
||||
|
||||
notification = WMCreateNotification(name, object, clientData);
|
||||
|
||||
WMPostNotification(notification);
|
||||
|
||||
WMReleaseNotification(notification);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************** Notification Queues ****************/
|
||||
|
||||
|
||||
typedef struct W_NotificationQueue {
|
||||
NotificationCenter *center;
|
||||
void *asapQueue;
|
||||
void *idleQueue;
|
||||
} NotificationQueue;
|
||||
|
||||
|
||||
/* default queue */
|
||||
static WMNotificationQueue *notificationQueue = NULL;
|
||||
|
||||
WMNotificationQueue*
|
||||
WMGetDefaultNotificationQueue(void)
|
||||
{
|
||||
return notificationQueue;
|
||||
}
|
||||
|
||||
|
||||
WMNotificationQueue*
|
||||
WMCreateNotificationQueue(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMDequeueNotificationMatching(WMNotificationQueue *queue, unsigned mask)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMEnqueueNotification(WMNotificationQueue *queue, WMNotification *notification,
|
||||
WMPostingStyle postingStyle)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMEnqueueCoalesceNotification(WMNotificationQueue *queue,
|
||||
WMNotification *notification,
|
||||
WMPostingStyle postingStyle,
|
||||
unsigned coalesceMask)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
293
WINGs/selection.c
Normal file
293
WINGs/selection.c
Normal file
@@ -0,0 +1,293 @@
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#if 0
|
||||
|
||||
typedef struct W_SelectionHandler {
|
||||
WMWidget *widget;
|
||||
Atom selection;
|
||||
void *clientData;
|
||||
WMSelectionProc *proc;
|
||||
WMHandlerID timerID;
|
||||
W_SelectionHandler *next;
|
||||
W_SelectionHandler *prev;
|
||||
} W_SelectionHandler;
|
||||
#endif
|
||||
|
||||
#define SELECTION_TIMEOUT 2000
|
||||
#define MAX_PROPERTY_SIZE 10*1024
|
||||
#if 0
|
||||
|
||||
|
||||
void
|
||||
WMWriteSelectionToClipboard(WMSelection *selection)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
WMSelection*
|
||||
WMCreateSelectionWithData(WMData *data, Atom type)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
#define MAX_PROPERTY_SIZE 100*1024
|
||||
|
||||
|
||||
static void
|
||||
handleSelectionEvent(XEvent *event, void *data)
|
||||
{
|
||||
W_SelectionHandler *handler = (W_SelectionHandler*)data;
|
||||
char *data = NULL;
|
||||
Atom type;
|
||||
int format, result;
|
||||
unsigned long numItems, bytesAfter;
|
||||
WMScreen *scr = WMWidgetScreen(handler->widget);
|
||||
|
||||
WMDeleteTimerHandler(handler->timerID);
|
||||
|
||||
if (handler->next)
|
||||
handler->next->prev = handler->prev;
|
||||
if (handler->prev)
|
||||
handler->prev->next = handler->next;
|
||||
if (handler == WMWidgetScreen(handler->widget)->selectionHandlerList)
|
||||
WMWidgetScreen(handler->widget)->selectionHandlerList = handler->next;
|
||||
|
||||
if (event->xselection.property == None) {
|
||||
char *name = XGetAtomName(event->xselection.display,
|
||||
handler->selection);
|
||||
char *form = XGetAtomName(event->xselection.display, handler->type);
|
||||
wwarning("error retrieving selection %s with form %s\n", name, form);
|
||||
if (name)
|
||||
XFree(name);
|
||||
if (form)
|
||||
XFree(form);
|
||||
free(handler);
|
||||
return;
|
||||
}
|
||||
|
||||
if (XGetWindowProperty(event->xselection.display,
|
||||
event->xselection.requestor, handler->property,
|
||||
0, MAX_PROPERTY_SIZE, False, AnyPropertyType,
|
||||
&type, &format, &numItems, &bytesAfter,
|
||||
&data) != Success || type == None) {
|
||||
if (data)
|
||||
XFree(data);
|
||||
free(handler);
|
||||
return;
|
||||
}
|
||||
if (bytesAfter!=0) {
|
||||
wwarning("data in selection is too large");
|
||||
if (data)
|
||||
XFree(data);
|
||||
free(handler);
|
||||
return;
|
||||
}
|
||||
if (type == XA_STRING || type == scr->compoundTextAtom) {
|
||||
if (format!=8) {
|
||||
wwarning("string in selection has format %i, which is invalid",
|
||||
format);
|
||||
if (data)
|
||||
XFree(data);
|
||||
free(handler);
|
||||
return;
|
||||
}
|
||||
(*handler->proc)();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
timeoutHandler(void *data)
|
||||
{
|
||||
W_SelectionHandler *handler = (W_SelectionHandler*)data;
|
||||
|
||||
wwarning("selection timed out");
|
||||
WMDeleteEventHandler(WMWidgetView(handler->widget), SelectionNotifyMask,
|
||||
handleSelectionEvent, data);
|
||||
if (handler->next)
|
||||
handler->next->prev = handler->prev;
|
||||
if (handler->prev)
|
||||
handler->prev->next = handler->next;
|
||||
if (handler == WMWidgetScreen(handler->widget)->selectionHandlerList)
|
||||
WMWidgetScreen(handler->widget)->selectionHandlerList = handler->next;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMGetSelection(WMWidget *widget, Atom selection, Atom type, Atom property,
|
||||
WMSelectionProc *proc, void *clientData, Time time)
|
||||
{
|
||||
WMScreen *scr = WMWidgetScreen(widget);
|
||||
void *data;
|
||||
Atom rtype;
|
||||
int bits;
|
||||
unsigned long len, bytes;
|
||||
unsigned char *data;
|
||||
int buffer = -1;
|
||||
|
||||
switch (selection) {
|
||||
case XA_CUT_BUFFER0:
|
||||
buffer = 0;
|
||||
break;
|
||||
case XA_CUT_BUFFER1:
|
||||
buffer = 1;
|
||||
break;
|
||||
case XA_CUT_BUFFER2:
|
||||
buffer = 2;
|
||||
break;
|
||||
case XA_CUT_BUFFER3:
|
||||
buffer = 3;
|
||||
break;
|
||||
case XA_CUT_BUFFER4:
|
||||
buffer = 4;
|
||||
break;
|
||||
case XA_CUT_BUFFER5:
|
||||
buffer = 5;
|
||||
break;
|
||||
case XA_CUT_BUFFER6:
|
||||
buffer = 6;
|
||||
break;
|
||||
case XA_CUT_BUFFER7:
|
||||
buffer = 7;
|
||||
break;
|
||||
}
|
||||
if (buffer >= 0) {
|
||||
char *data;
|
||||
int size;
|
||||
|
||||
data = XFetchBuffer(scr->display, &size, buffer);
|
||||
|
||||
} else {
|
||||
W_SelectionHandler *handler;
|
||||
|
||||
XDeleteProperty(scr->display, WMWidgetXID(widget), selection);
|
||||
XConvertSelection(scr->display, selection, type, property,
|
||||
WMWidgetXID(widget), time);
|
||||
|
||||
handler = wmalloc(sizeof(W_SelectionHandler));
|
||||
handler->widget = widget;
|
||||
handler->selection = selection;
|
||||
handler->type = type;
|
||||
handler->property = property;
|
||||
handler->clientData = clientData;
|
||||
handler->proc = proc;
|
||||
handler->timerID = WMAddTimerHandler(SELECTION_TIMEOUT,
|
||||
timeoutHandler, handler);
|
||||
|
||||
handler->next = scr->selectionHandlerList;
|
||||
handler->prev = NULL;
|
||||
if (scr->selectionHandlerList)
|
||||
scr->selectionHandlerList->prev = handler;
|
||||
scr->selectionHandlerList = handler;
|
||||
|
||||
WMCreateEventHandler(WMWidgetView(widget), SelectionNotifyMask,
|
||||
handleSelectionEvent, handler);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static void
|
||||
timeoutHandler(void *data)
|
||||
{
|
||||
*(int*)data = 1;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
W_GetTextSelection(WMScreen *scr, Atom selection)
|
||||
{
|
||||
int buffer = -1;
|
||||
|
||||
switch (selection) {
|
||||
case XA_CUT_BUFFER0:
|
||||
buffer = 0;
|
||||
break;
|
||||
case XA_CUT_BUFFER1:
|
||||
buffer = 1;
|
||||
break;
|
||||
case XA_CUT_BUFFER2:
|
||||
buffer = 2;
|
||||
break;
|
||||
case XA_CUT_BUFFER3:
|
||||
buffer = 3;
|
||||
break;
|
||||
case XA_CUT_BUFFER4:
|
||||
buffer = 4;
|
||||
break;
|
||||
case XA_CUT_BUFFER5:
|
||||
buffer = 5;
|
||||
break;
|
||||
case XA_CUT_BUFFER6:
|
||||
buffer = 6;
|
||||
break;
|
||||
case XA_CUT_BUFFER7:
|
||||
buffer = 7;
|
||||
break;
|
||||
}
|
||||
if (buffer >= 0) {
|
||||
char *data;
|
||||
int size;
|
||||
|
||||
data = XFetchBuffer(scr->display, &size, buffer);
|
||||
|
||||
return data;
|
||||
} else {
|
||||
unsigned char *data;
|
||||
int bits;
|
||||
Atom rtype;
|
||||
unsigned long len, bytes;
|
||||
WMHandlerID timer;
|
||||
int timeout = 0;
|
||||
XEvent ev;
|
||||
|
||||
XDeleteProperty(scr->display, scr->groupLeader, scr->clipboardAtom);
|
||||
XConvertSelection(scr->display, selection, XA_STRING,
|
||||
scr->clipboardAtom, scr->groupLeader,
|
||||
scr->lastEventTime);
|
||||
|
||||
timer = WMAddTimerHandler(1000, timeoutHandler, &timeout);
|
||||
|
||||
while (!XCheckTypedWindowEvent(scr->display, scr->groupLeader,
|
||||
SelectionNotify, &ev) && !timeout);
|
||||
|
||||
if (!timeout) {
|
||||
WMDeleteTimerHandler(timer);
|
||||
} else {
|
||||
wwarning("selection retrieval timed out");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* nobody owns the selection */
|
||||
if (ev.xselection.property == None) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (XGetWindowProperty(scr->display, scr->groupLeader,
|
||||
scr->clipboardAtom, 0, MAX_PROPERTY_SIZE,
|
||||
False, XA_STRING, &rtype, &bits, &len,
|
||||
&bytes, &data)!=Success) {
|
||||
return NULL;
|
||||
}
|
||||
if (rtype!=XA_STRING || bits!=8) {
|
||||
wwarning("invalid data in text selection");
|
||||
if (data)
|
||||
XFree(data);
|
||||
return NULL;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
51
WINGs/testmywidget.c
Normal file
51
WINGs/testmywidget.c
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
|
||||
#include <WINGs.h>
|
||||
#include <WUtil.h>
|
||||
|
||||
#include "mywidget.h"
|
||||
|
||||
|
||||
void
|
||||
wAbort()
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Display *dpy = XOpenDisplay("");
|
||||
WMScreen *scr;
|
||||
WMWindow *win;
|
||||
MyWidget *thing;
|
||||
|
||||
|
||||
WMInitializeApplication("Test", &argc, argv);
|
||||
|
||||
if (!dpy) {
|
||||
wfatal("could not open display");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
scr = WMCreateSimpleApplicationScreen(dpy);
|
||||
|
||||
/* init our widget */
|
||||
InitMyWidget(scr);
|
||||
|
||||
win = WMCreateWindow(scr, "test");
|
||||
WMResizeWidget(win, 150, 50);
|
||||
|
||||
thing = CreateMyWidget(win);
|
||||
SetMyWidgetText(thing, "The Test");
|
||||
WMResizeWidget(thing, 100, 20);
|
||||
WMMoveWidget(thing, 10, 10);
|
||||
|
||||
WMRealizeWidget(win);
|
||||
WMMapSubwidgets(win);
|
||||
WMMapWidget(win);
|
||||
|
||||
WMScreenMainLoop(scr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
420
WINGs/userdefaults.c
Normal file
420
WINGs/userdefaults.c
Normal file
@@ -0,0 +1,420 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "WUtil.h"
|
||||
|
||||
#include <proplist.h>
|
||||
|
||||
|
||||
typedef struct W_UserDefaults {
|
||||
proplist_t defaults;
|
||||
|
||||
proplist_t appDomain;
|
||||
|
||||
proplist_t searchListArray;
|
||||
proplist_t *searchList; /* cache for searchListArray */
|
||||
|
||||
char dirty;
|
||||
|
||||
} UserDefaults;
|
||||
|
||||
|
||||
static UserDefaults *sharedUserDefaults = NULL;
|
||||
|
||||
extern char *WMGetApplicationName();
|
||||
|
||||
#define DEFAULTS_DIR "/Defaults"
|
||||
|
||||
|
||||
char*
|
||||
wusergnusteppath()
|
||||
{
|
||||
char *path;
|
||||
char *gspath;
|
||||
int pathlen;
|
||||
|
||||
gspath = getenv("GNUSTEP_USER_ROOT");
|
||||
if (gspath) {
|
||||
gspath = wexpandpath(gspath);
|
||||
pathlen = strlen(gspath) + 4;
|
||||
path = wmalloc(pathlen);
|
||||
strcpy(path, gspath);
|
||||
free(gspath);
|
||||
} else {
|
||||
pathlen = strlen(wgethomedir()) + 10;
|
||||
path = wmalloc(pathlen);
|
||||
strcpy(path, wgethomedir());
|
||||
strcat(path, "/GNUstep");
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
wdefaultspathfordomain(char *domain)
|
||||
{
|
||||
char *path;
|
||||
char *gspath;
|
||||
|
||||
gspath = wusergnusteppath();
|
||||
path = wmalloc(strlen(gspath)+strlen(DEFAULTS_DIR)+strlen(domain)+4);
|
||||
strcpy(path, gspath);
|
||||
free(gspath);
|
||||
strcat(path, DEFAULTS_DIR);
|
||||
strcat(path, "/");
|
||||
strcat(path, domain);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
saveDefaultsChanges(void)
|
||||
{
|
||||
if (sharedUserDefaults && sharedUserDefaults->dirty) {
|
||||
PLSave(sharedUserDefaults->appDomain, YES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMUserDefaults*
|
||||
WMGetStandardUserDefaults(void)
|
||||
{
|
||||
if (!sharedUserDefaults) {
|
||||
WMUserDefaults *defaults;
|
||||
|
||||
proplist_t domain;
|
||||
proplist_t key;
|
||||
char *path;
|
||||
int i;
|
||||
|
||||
defaults = wmalloc(sizeof(WMUserDefaults));
|
||||
memset(defaults, 0, sizeof(WMUserDefaults));
|
||||
|
||||
defaults->defaults = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
|
||||
|
||||
defaults->searchList = wmalloc(sizeof(proplist_t)*3);
|
||||
|
||||
/* application domain */
|
||||
key = PLMakeString(WMGetApplicationName());
|
||||
defaults->searchList[0] = key;
|
||||
|
||||
/* temporary kluge */
|
||||
if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
|
||||
domain = NULL;
|
||||
path = NULL;
|
||||
} else {
|
||||
path = wdefaultspathfordomain(PLGetString(key));
|
||||
|
||||
domain = PLGetProplistWithPath(path);
|
||||
}
|
||||
if (!domain) {
|
||||
proplist_t p;
|
||||
|
||||
domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
|
||||
if (path) {
|
||||
p = PLMakeString(path);
|
||||
PLSetFilename(domain, p);
|
||||
PLRelease(p);
|
||||
}
|
||||
}
|
||||
if (path)
|
||||
free(path);
|
||||
|
||||
defaults->appDomain = domain;
|
||||
|
||||
if (domain)
|
||||
PLInsertDictionaryEntry(defaults->defaults, key, domain);
|
||||
|
||||
PLRelease(key);
|
||||
|
||||
/* global domain */
|
||||
key = PLMakeString("WMGLOBAL");
|
||||
defaults->searchList[1] = key;
|
||||
|
||||
path = wdefaultspathfordomain(PLGetString(key));
|
||||
|
||||
domain = PLGetProplistWithPath(path);
|
||||
|
||||
free(path);
|
||||
|
||||
if (!domain)
|
||||
domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
|
||||
|
||||
if (domain)
|
||||
PLInsertDictionaryEntry(defaults->defaults, key, domain);
|
||||
|
||||
PLRelease(key);
|
||||
|
||||
/* terminate list */
|
||||
defaults->searchList[2] = NULL;
|
||||
|
||||
defaults->searchListArray=PLMakeArrayFromElements(NULL,NULL);
|
||||
|
||||
|
||||
i = 0;
|
||||
while (defaults->searchList[i]) {
|
||||
PLAppendArrayElement(defaults->searchListArray,
|
||||
defaults->searchList[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
sharedUserDefaults = defaults;
|
||||
|
||||
/* set to save changes in defaults when program is exited */
|
||||
atexit(saveDefaultsChanges);
|
||||
}
|
||||
|
||||
return sharedUserDefaults;
|
||||
}
|
||||
|
||||
|
||||
|
||||
proplist_t
|
||||
WMGetUDObjectForKey(WMUserDefaults *database, char *defaultName)
|
||||
{
|
||||
proplist_t domainName, domain;
|
||||
proplist_t object = NULL;
|
||||
proplist_t key = PLMakeString(defaultName);
|
||||
int i = 0;
|
||||
|
||||
while (database->searchList[i] && !object) {
|
||||
domainName = database->searchList[i];
|
||||
domain = PLGetDictionaryEntry(database->defaults, domainName);
|
||||
if (domain) {
|
||||
object = PLGetDictionaryEntry(domain, key);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
PLRelease(key);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetUDObjectForKey(WMUserDefaults *database, proplist_t object,
|
||||
char *defaultName)
|
||||
{
|
||||
proplist_t key = PLMakeString(defaultName);
|
||||
|
||||
database->dirty = 1;
|
||||
|
||||
PLInsertDictionaryEntry(database->appDomain, key, object);
|
||||
PLRelease(key);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMRemoveUDObjectForKey(WMUserDefaults *database, char *defaultName)
|
||||
{
|
||||
proplist_t key = PLMakeString(defaultName);
|
||||
|
||||
database->dirty = 1;
|
||||
|
||||
PLRemoveDictionaryEntry(database->appDomain, key);
|
||||
|
||||
PLRelease(key);
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMGetUDStringForKey(WMUserDefaults *database, char *defaultName)
|
||||
{
|
||||
proplist_t val;
|
||||
|
||||
val = WMGetUDObjectForKey(database, defaultName);
|
||||
|
||||
if (!val)
|
||||
return NULL;
|
||||
|
||||
if (!PLIsString(val))
|
||||
return NULL;
|
||||
|
||||
return wstrdup(PLGetString(val));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetUDIntegerForKey(WMUserDefaults *database, char *defaultName)
|
||||
{
|
||||
proplist_t val;
|
||||
char *str;
|
||||
int value;
|
||||
|
||||
val = WMGetUDObjectForKey(database, defaultName);
|
||||
|
||||
if (!val)
|
||||
return 0;
|
||||
|
||||
if (!PLIsString(val))
|
||||
return 0;
|
||||
|
||||
str = PLGetString(val);
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
if (sscanf(str, "%i", &value)!=1)
|
||||
return 0;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
WMGetUDFloatForKey(WMUserDefaults *database, char *defaultName)
|
||||
{
|
||||
proplist_t val;
|
||||
char *str;
|
||||
float value;
|
||||
|
||||
val = WMGetUDObjectForKey(database, defaultName);
|
||||
|
||||
if (!val)
|
||||
return 0.0;
|
||||
|
||||
if (!PLIsString(val))
|
||||
return 0.0;
|
||||
|
||||
str = PLGetString(val);
|
||||
if (!str)
|
||||
return 0.0;
|
||||
|
||||
if (sscanf(str, "%f", &value)!=1)
|
||||
return 0.0;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Bool
|
||||
WMGetUDBoolForKey(WMUserDefaults *database, char *defaultName)
|
||||
{
|
||||
proplist_t val;
|
||||
int value;
|
||||
char *str;
|
||||
|
||||
val = WMGetUDObjectForKey(database, defaultName);
|
||||
|
||||
if (!val)
|
||||
return False;
|
||||
|
||||
if (!PLIsString(val))
|
||||
return False;
|
||||
|
||||
str = PLGetString(val);
|
||||
if (!str)
|
||||
return False;
|
||||
|
||||
if (sscanf(str, "%i", &value)==1 && value!=0)
|
||||
return True;
|
||||
|
||||
if (strcasecmp(str, "YES")==0)
|
||||
return True;
|
||||
|
||||
if (strcasecmp(str, "Y")==0)
|
||||
return True;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetUDIntegerForKey(WMUserDefaults *database, int value, char *defaultName)
|
||||
{
|
||||
proplist_t object;
|
||||
char buffer[128];
|
||||
|
||||
sprintf(buffer, "%i", value);
|
||||
object = PLMakeString(buffer);
|
||||
|
||||
WMSetUDObjectForKey(database, object, defaultName);
|
||||
PLRelease(object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetUDStringForKey(WMUserDefaults *database, char *value, char *defaultName)
|
||||
{
|
||||
proplist_t object;
|
||||
|
||||
object = PLMakeString(value);
|
||||
|
||||
WMSetUDObjectForKey(database, object, defaultName);
|
||||
PLRelease(object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetUDFloatForKey(WMUserDefaults *database, float value, char *defaultName)
|
||||
{
|
||||
proplist_t object;
|
||||
char buffer[128];
|
||||
|
||||
sprintf(buffer, "%f", value);
|
||||
object = PLMakeString(buffer);
|
||||
|
||||
WMSetUDObjectForKey(database, object, defaultName);
|
||||
PLRelease(object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetUDBoolForKey(WMUserDefaults *database, Bool value, char *defaultName)
|
||||
{
|
||||
static proplist_t yes = NULL, no = NULL;
|
||||
|
||||
if (!yes) {
|
||||
yes = PLMakeString("YES");
|
||||
no = PLMakeString("NO");
|
||||
}
|
||||
|
||||
WMSetUDObjectForKey(database, value ? yes : no, defaultName);
|
||||
}
|
||||
|
||||
|
||||
proplist_t
|
||||
WMGetUDSearchList(WMUserDefaults *database)
|
||||
{
|
||||
return database->searchListArray;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetUDSearchList(WMUserDefaults *database, proplist_t list)
|
||||
{
|
||||
int i, c;
|
||||
|
||||
if (database->searchList) {
|
||||
i = 0;
|
||||
while (database->searchList[i]) {
|
||||
PLRelease(database->searchList[i]);
|
||||
i++;
|
||||
}
|
||||
free(database->searchList);
|
||||
}
|
||||
if (database->searchListArray) {
|
||||
PLRelease(database->searchListArray);
|
||||
}
|
||||
|
||||
c = PLGetNumberOfElements(list);
|
||||
database->searchList = wmalloc(sizeof(proplist_t)*(c+1));
|
||||
|
||||
for (i=0; i<c; i++) {
|
||||
database->searchList[i] = PLGetArrayElement(list, i);
|
||||
}
|
||||
|
||||
database->searchListArray = PLDeepCopy(list);
|
||||
}
|
||||
|
||||
|
||||
50
WINGs/usleep.c
Normal file
50
WINGs/usleep.c
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
|
||||
#include "../src/config.h"
|
||||
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef _AIX
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SELECT)
|
||||
|
||||
|
||||
|
||||
void
|
||||
wusleep(unsigned int microsecs)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set rd, wr, ex;
|
||||
FD_ZERO(&rd);
|
||||
FD_ZERO(&wr);
|
||||
FD_ZERO(&ex);
|
||||
tv.tv_sec = microsecs / 1000000u;
|
||||
tv.tv_usec = microsecs % 1000000u;
|
||||
select(1, &rd, &wr, &ex, &tv);
|
||||
}
|
||||
|
||||
#else /* not HAVE_SELECT */
|
||||
|
||||
# ifdef HAVE_POLL
|
||||
|
||||
void
|
||||
wusleep(unsigned int microsecs)
|
||||
{
|
||||
poll((struct poll *) 0, (size_t) 0, microsecs/1000);
|
||||
}
|
||||
|
||||
# else /* ! HAVE_POLL */
|
||||
|
||||
oops!
|
||||
|
||||
# endif /* !HAVE_POLL */
|
||||
#endif /* !HAVE_SELECT */
|
||||
301
WINGs/wapplication.c
Normal file
301
WINGs/wapplication.c
Normal file
@@ -0,0 +1,301 @@
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
/* Xmd.h which is indirectly included by GNUstep.h defines BOOL,
|
||||
* but libPropList also defines it. So we do this kluge to get rid of BOOL
|
||||
* temporarily */
|
||||
#ifdef BOOL
|
||||
# define WINGS_BOOL
|
||||
# undef BOOL
|
||||
#endif
|
||||
|
||||
#include "GNUstep.h"
|
||||
|
||||
#ifdef WINGS_BOOL
|
||||
# define BOOL
|
||||
# undef WINGS_BOOL
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
extern void W_ReadConfigurations(void);
|
||||
|
||||
extern void W_InitNotificationCenter(void);
|
||||
|
||||
|
||||
typedef struct W_Application {
|
||||
char *applicationName;
|
||||
int argc;
|
||||
char **argv;
|
||||
char *resourcePath;
|
||||
} W_Application;
|
||||
|
||||
|
||||
struct W_Application WMApplication;
|
||||
|
||||
|
||||
char *_WINGS_progname = NULL;
|
||||
|
||||
|
||||
|
||||
Bool
|
||||
W_ApplicationInitialized(void)
|
||||
{
|
||||
return _WINGS_progname!=NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMInitializeApplication(char *applicationName, int *argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(argc!=NULL);
|
||||
assert(argv!=NULL);
|
||||
assert(applicationName!=NULL);
|
||||
|
||||
_WINGS_progname = argv[0];
|
||||
|
||||
WMApplication.applicationName = wstrdup(applicationName);
|
||||
WMApplication.argc = *argc;
|
||||
|
||||
WMApplication.argv = wmalloc((*argc+1)*sizeof(char*));
|
||||
for (i=0; i<*argc; i++) {
|
||||
WMApplication.argv[i] = wstrdup(argv[i]);
|
||||
}
|
||||
WMApplication.argv[i] = NULL;
|
||||
|
||||
/* initialize notification center */
|
||||
W_InitNotificationCenter();
|
||||
|
||||
/* read general configuration data for WINGs */
|
||||
W_ReadConfigurations();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetResourcePath(char *path)
|
||||
{
|
||||
if (WMApplication.resourcePath)
|
||||
free(WMApplication.resourcePath);
|
||||
WMApplication.resourcePath = wstrdup(path);
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMGetApplicationName()
|
||||
{
|
||||
return WMApplication.applicationName;
|
||||
}
|
||||
|
||||
|
||||
static char*
|
||||
checkFile(char *path, char *folder, char *ext, char *resource)
|
||||
{
|
||||
char *ret;
|
||||
int extralen;
|
||||
|
||||
extralen = (ext ? strlen(ext) : 0) + (folder ? strlen(folder) : 0) + 4;
|
||||
ret = wmalloc(strlen(path)+strlen(resource)+extralen+8);
|
||||
strcpy(ret, path);
|
||||
if (folder) {
|
||||
strcat(ret, "/");
|
||||
strcat(ret, folder);
|
||||
}
|
||||
if (ext) {
|
||||
strcat(ret, "/");
|
||||
strcat(ret, ext);
|
||||
}
|
||||
strcat(ret, "/");
|
||||
strcat(ret, resource);
|
||||
|
||||
if (access(ret, F_OK)!=0) {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMPathForResourceOfType(char *resource, char *ext)
|
||||
{
|
||||
char *path = NULL;
|
||||
char *tmp, *appdir;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Paths are searched in this order:
|
||||
* - resourcePath/ext
|
||||
* - argv[0]/ext
|
||||
* - GNUSTEP_USER_ROOT/Apps/ApplicationName.app/ext
|
||||
* - ~/GNUstep/Apps/ApplicationName.app/ext
|
||||
* - GNUSTEP_LOCAL_ROOT/Apps/ApplicationName.app/ext
|
||||
* - /usr/local/GNUstep/Apps/ApplicationName.app/ext
|
||||
* - GNUSTEP_SYSTEM_ROOT/Apps/ApplicationName.app/ext
|
||||
* - /usr/GNUstep/Apps/ApplicationName.app/ext
|
||||
*/
|
||||
|
||||
if (WMApplication.resourcePath) {
|
||||
path = checkFile(WMApplication.resourcePath, NULL, ext, resource);
|
||||
if (path)
|
||||
return path;
|
||||
}
|
||||
|
||||
if (WMApplication.argv[0]) {
|
||||
tmp = wstrdup(WMApplication.argv[0]);
|
||||
i = strlen(tmp);
|
||||
while (i > 0 && tmp[i]!='/')
|
||||
i--;
|
||||
tmp[i] = 0;
|
||||
if (i>0) {
|
||||
path = checkFile(tmp, NULL, ext, resource);
|
||||
} else {
|
||||
path = NULL;
|
||||
}
|
||||
free(tmp);
|
||||
if (path)
|
||||
return path;
|
||||
}
|
||||
|
||||
appdir = wmalloc(strlen(WMApplication.applicationName)+8);
|
||||
sprintf(appdir, "Apps/%s.app", WMApplication.applicationName);
|
||||
|
||||
if (getenv("GNUSTEP_USER_ROOT")) {
|
||||
path = checkFile(getenv("GNUSTEP_USER_ROOT"), appdir, ext, resource);
|
||||
if (path) {
|
||||
free(appdir);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
tmp = wusergnusteppath();
|
||||
if (tmp) {
|
||||
path = checkFile(tmp, appdir, ext, resource);
|
||||
free(tmp);
|
||||
if (path) {
|
||||
free(appdir);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
if (getenv("GNUSTEP_LOCAL_ROOT")) {
|
||||
path = checkFile(getenv("GNUSTEP_LOCAL_ROOT"), appdir, ext, resource);
|
||||
if (path) {
|
||||
free(appdir);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
path = checkFile("/usr/local/GNUstep", appdir, ext, resource);
|
||||
if (path) {
|
||||
free(appdir);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
if (getenv("GNUSTEP_SYSTEM_ROOT")) {
|
||||
path = checkFile(getenv("GNUSTEP_SYSTEM_ROOT"), appdir, ext, resource);
|
||||
if (path) {
|
||||
free(appdir);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
path = checkFile("/usr/GNUstep", appdir, ext, resource);
|
||||
if (path) {
|
||||
free(appdir);
|
||||
return path;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/********************* WMScreen related stuff ********************/
|
||||
|
||||
|
||||
void
|
||||
WMSetApplicationIconImage(WMScreen *scr, WMPixmap *icon)
|
||||
{
|
||||
if (scr->applicationIcon)
|
||||
WMReleasePixmap(scr->applicationIcon);
|
||||
|
||||
scr->applicationIcon = WMRetainPixmap(icon);
|
||||
|
||||
if (scr->groupLeader) {
|
||||
XWMHints *hints;
|
||||
|
||||
hints = XGetWMHints(scr->display, scr->groupLeader);
|
||||
hints->flags |= IconPixmapHint|IconMaskHint;
|
||||
hints->icon_pixmap = icon->pixmap;
|
||||
hints->icon_mask = icon->mask;
|
||||
|
||||
XSetWMHints(scr->display, scr->groupLeader, hints);
|
||||
XFree(hints);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMPixmap*
|
||||
WMGetApplicationIconImage(WMScreen *scr)
|
||||
{
|
||||
return scr->applicationIcon;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetApplicationHasAppIcon(WMScreen *scr, Bool flag)
|
||||
{
|
||||
scr->aflags.hasAppIcon = flag;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_InitApplication(WMScreen *scr)
|
||||
{
|
||||
Window leader;
|
||||
XClassHint *classHint;
|
||||
XWMHints *hints;
|
||||
|
||||
leader = XCreateSimpleWindow(scr->display, scr->rootWin, -1, -1,
|
||||
1, 1, 0, 0, 0);
|
||||
|
||||
if (!scr->aflags.simpleApplication) {
|
||||
classHint = XAllocClassHint();
|
||||
classHint->res_name = "groupLeader";
|
||||
classHint->res_class = WMApplication.applicationName;
|
||||
XSetClassHint(scr->display, leader, classHint);
|
||||
XFree(classHint);
|
||||
|
||||
XSetCommand(scr->display, leader, WMApplication.argv,
|
||||
WMApplication.argc);
|
||||
|
||||
hints = XAllocWMHints();
|
||||
|
||||
hints->flags = WindowGroupHint;
|
||||
hints->window_group = leader;
|
||||
|
||||
if (scr->applicationIcon) {
|
||||
hints->flags |= IconPixmapHint;
|
||||
hints->icon_pixmap = scr->applicationIcon->pixmap;
|
||||
if (scr->applicationIcon->mask) {
|
||||
hints->flags |= IconMaskHint;
|
||||
hints->icon_mask = scr->applicationIcon->mask;
|
||||
}
|
||||
}
|
||||
|
||||
XSetWMHints(scr->display, leader, hints);
|
||||
|
||||
XFree(hints);
|
||||
}
|
||||
scr->groupLeader = leader;
|
||||
}
|
||||
|
||||
|
||||
911
WINGs/wbrowser.c
Normal file
911
WINGs/wbrowser.c
Normal file
@@ -0,0 +1,911 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
char *WMBrowserDidScrollNotification = "WMBrowserDidScrollNotification";
|
||||
|
||||
|
||||
typedef struct W_Browser {
|
||||
W_Class widgetClass;
|
||||
W_View *view;
|
||||
|
||||
char **titles;
|
||||
WMList **columns;
|
||||
|
||||
short columnCount;
|
||||
short usedColumnCount; /* columns actually being used */
|
||||
short minColumnWidth;
|
||||
|
||||
short maxVisibleColumns;
|
||||
short firstVisibleColumn;
|
||||
|
||||
short titleHeight;
|
||||
|
||||
short selectedColumn;
|
||||
|
||||
WMSize columnSize;
|
||||
|
||||
|
||||
void *clientData;
|
||||
WMAction *action;
|
||||
void *doubleClientData;
|
||||
WMAction *doubleAction;
|
||||
|
||||
WMBrowserFillColumnProc *fillColumn;
|
||||
|
||||
WMScroller *scroller;
|
||||
|
||||
char *pathSeparator;
|
||||
|
||||
struct {
|
||||
unsigned int isTitled:1;
|
||||
unsigned int allowMultipleSelection:1;
|
||||
unsigned int hasScroller:1;
|
||||
|
||||
/* */
|
||||
unsigned int loaded:1;
|
||||
unsigned int loadingColumn:1;
|
||||
} flags;
|
||||
} Browser;
|
||||
|
||||
|
||||
#define COLUMN_SPACING 4
|
||||
#define TITLE_SPACING 2
|
||||
|
||||
#define DEFAULT_WIDTH 305
|
||||
#define DEFAULT_HEIGHT 200
|
||||
#define DEFAULT_HAS_SCROLLER True
|
||||
|
||||
#define DEFAULT_SEPARATOR "/"
|
||||
|
||||
#define COLUMN_IS_VISIBLE(b, c) ((c) >= (b)->firstVisibleColumn \
|
||||
&& (c) < (b)->firstVisibleColumn + (b)->maxVisibleColumns)
|
||||
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void destroyBrowser(WMBrowser *bPtr);
|
||||
|
||||
static void setupScroller(WMBrowser *bPtr);
|
||||
|
||||
static void scrollToColumn(WMBrowser *bPtr, int column);
|
||||
|
||||
static void paintItem(WMList *lPtr, Drawable d, char *text, int state,
|
||||
WMRect *rect);
|
||||
|
||||
static void loadColumn(WMBrowser *bPtr, int column);
|
||||
|
||||
|
||||
static void resizeBrowser(WMWidget*, unsigned int, unsigned int);
|
||||
|
||||
W_ViewProcedureTable _BrowserViewProcedures = {
|
||||
NULL,
|
||||
resizeBrowser,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
WMBrowser*
|
||||
WMCreateBrowser(WMWidget *parent)
|
||||
{
|
||||
WMBrowser *bPtr;
|
||||
int i;
|
||||
|
||||
bPtr = wmalloc(sizeof(WMBrowser));
|
||||
memset(bPtr, 0, sizeof(WMBrowser));
|
||||
|
||||
bPtr->widgetClass = WC_Browser;
|
||||
|
||||
bPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!bPtr->view) {
|
||||
free(bPtr);
|
||||
return NULL;
|
||||
}
|
||||
bPtr->view->self = bPtr;
|
||||
|
||||
WMCreateEventHandler(bPtr->view, ExposureMask|StructureNotifyMask
|
||||
|ClientMessageMask, handleEvents, bPtr);
|
||||
|
||||
/* default configuration */
|
||||
bPtr->flags.hasScroller = DEFAULT_HAS_SCROLLER;
|
||||
|
||||
bPtr->titleHeight = 20;
|
||||
bPtr->flags.isTitled = 1;
|
||||
bPtr->maxVisibleColumns = 2;
|
||||
|
||||
resizeBrowser(bPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
||||
bPtr->pathSeparator = wstrdup(DEFAULT_SEPARATOR);
|
||||
|
||||
if (bPtr->flags.hasScroller)
|
||||
setupScroller(bPtr);
|
||||
|
||||
for (i=0; i<bPtr->maxVisibleColumns; i++) {
|
||||
WMAddBrowserColumn(bPtr);
|
||||
}
|
||||
bPtr->usedColumnCount = 0;
|
||||
|
||||
bPtr->selectedColumn = -1;
|
||||
|
||||
return bPtr;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetBrowserNumberOfColumns(WMBrowser *bPtr)
|
||||
{
|
||||
return bPtr->usedColumnCount;
|
||||
}
|
||||
|
||||
void
|
||||
WMSetBrowserPathSeparator(WMBrowser *bPtr, char *separator)
|
||||
{
|
||||
if (bPtr->pathSeparator)
|
||||
free(bPtr->pathSeparator);
|
||||
bPtr->pathSeparator = wstrdup(separator);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
drawTitleOfColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
WMScreen *scr = bPtr->view->screen;
|
||||
int x;
|
||||
|
||||
x=(column-bPtr->firstVisibleColumn)*(bPtr->columnSize.width+COLUMN_SPACING);
|
||||
|
||||
XFillRectangle(scr->display, bPtr->view->window, W_GC(scr->darkGray), x, 0,
|
||||
bPtr->columnSize.width, bPtr->titleHeight);
|
||||
W_DrawRelief(scr, bPtr->view->window, x, 0,
|
||||
bPtr->columnSize.width, bPtr->titleHeight, WRSunken);
|
||||
|
||||
if (column < bPtr->usedColumnCount && bPtr->titles[column])
|
||||
W_PaintText(bPtr->view, bPtr->view->window, scr->boldFont, x,
|
||||
(bPtr->titleHeight-scr->boldFont->height)/2,
|
||||
bPtr->columnSize.width, WACenter, W_GC(scr->white),
|
||||
False, bPtr->titles[column], strlen(bPtr->titles[column]));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetBrowserColumnTitle(WMBrowser *bPtr, int column, char *title)
|
||||
{
|
||||
assert(column >= 0);
|
||||
assert(column < bPtr->usedColumnCount);
|
||||
|
||||
if (bPtr->titles[column])
|
||||
free(bPtr->titles[column]);
|
||||
|
||||
bPtr->titles[column] = wstrdup(title);
|
||||
|
||||
if (COLUMN_IS_VISIBLE(bPtr, column) && bPtr->flags.isTitled) {
|
||||
drawTitleOfColumn(bPtr, column);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMList*
|
||||
WMGetBrowserListInColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
if (column < 0 || column >= bPtr->usedColumnCount)
|
||||
return NULL;
|
||||
|
||||
return bPtr->columns[column];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetBrowserFillColumnProc(WMBrowser *bPtr, WMBrowserFillColumnProc *proc)
|
||||
{
|
||||
bPtr->fillColumn = proc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetBrowserFirstVisibleColumn(WMBrowser *bPtr)
|
||||
{
|
||||
return bPtr->firstVisibleColumn;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
removeColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
int i;
|
||||
WMList **clist;
|
||||
char **tlist;
|
||||
|
||||
if (column >= bPtr->usedColumnCount)
|
||||
return;
|
||||
|
||||
if (column < bPtr->maxVisibleColumns) {
|
||||
int tmp;
|
||||
for (i=column; i < bPtr->maxVisibleColumns; i++) {
|
||||
if (bPtr->titles[i])
|
||||
free(bPtr->titles[i]);
|
||||
bPtr->titles[i] = NULL;
|
||||
|
||||
WMClearList(bPtr->columns[i]);
|
||||
bPtr->usedColumnCount--;
|
||||
}
|
||||
tmp = bPtr->columnCount;
|
||||
for (i=bPtr->maxVisibleColumns; i < tmp; i++) {
|
||||
if (bPtr->titles[i])
|
||||
free(bPtr->titles[i]);
|
||||
bPtr->titles[i] = NULL;
|
||||
|
||||
WMDestroyWidget(bPtr->columns[i]);
|
||||
bPtr->columns[i] = NULL;
|
||||
bPtr->columnCount--;
|
||||
bPtr->usedColumnCount--;
|
||||
}
|
||||
} else {
|
||||
int tmp = bPtr->columnCount;
|
||||
for (i=column; i < tmp; i++) {
|
||||
if (bPtr->titles[i])
|
||||
free(bPtr->titles[i]);
|
||||
bPtr->titles[i] = NULL;
|
||||
|
||||
WMDestroyWidget(bPtr->columns[i]);
|
||||
bPtr->columns[i] = NULL;
|
||||
bPtr->columnCount--;
|
||||
bPtr->usedColumnCount--;
|
||||
}
|
||||
}
|
||||
clist = wmalloc(sizeof(WMList*)*bPtr->columnCount);
|
||||
tlist = wmalloc(sizeof(char*)*bPtr->columnCount);
|
||||
memcpy(clist, bPtr->columns, sizeof(WMList*)*bPtr->columnCount);
|
||||
memcpy(tlist, bPtr->titles, sizeof(char*)*bPtr->columnCount);
|
||||
free(bPtr->titles);
|
||||
free(bPtr->columns);
|
||||
bPtr->titles = tlist;
|
||||
bPtr->columns = clist;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMListItem*
|
||||
WMGetBrowserSelectedItemInColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
if ((column < 0) || (column > bPtr->columnCount))
|
||||
return NULL;
|
||||
|
||||
return WMGetListSelectedItem(bPtr->columns[column]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
WMGetBrowserSelectedColumn(WMBrowser *bPtr)
|
||||
{
|
||||
return bPtr->selectedColumn;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetBrowserSelectedRowInColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
if (column >= 0 && column < bPtr->columnCount) {
|
||||
return WMGetListSelectedItemRow(bPtr->columns[column]);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetBrowserTitled(WMBrowser *bPtr, Bool flag)
|
||||
{
|
||||
int i;
|
||||
int columnX, columnY;
|
||||
|
||||
if (bPtr->flags.isTitled == flag)
|
||||
return;
|
||||
|
||||
columnX = 0;
|
||||
|
||||
if (!bPtr->flags.isTitled) {
|
||||
columnY = TITLE_SPACING + bPtr->titleHeight;
|
||||
|
||||
bPtr->columnSize.height -= columnY;
|
||||
|
||||
for (i=0; i<bPtr->columnCount; i++) {
|
||||
WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
|
||||
bPtr->columnSize.height);
|
||||
|
||||
columnX = WMWidgetView(bPtr->columns[i])->pos.x;
|
||||
|
||||
WMMoveWidget(bPtr->columns[i], columnX, columnY);
|
||||
}
|
||||
} else {
|
||||
bPtr->columnSize.height += TITLE_SPACING + bPtr->titleHeight;
|
||||
|
||||
for (i=0; i<bPtr->columnCount; i++) {
|
||||
WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
|
||||
bPtr->columnSize.height);
|
||||
|
||||
columnX = WMWidgetView(bPtr->columns[i])->pos.x;
|
||||
|
||||
WMMoveWidget(bPtr->columns[i], columnX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bPtr->flags.isTitled = flag;
|
||||
}
|
||||
|
||||
|
||||
WMListItem*
|
||||
WMAddSortedBrowserItem(WMBrowser *bPtr, int column, char *text, Bool isBranch)
|
||||
{
|
||||
WMListItem *item;
|
||||
|
||||
if (column < 0 || column >= bPtr->columnCount)
|
||||
return NULL;
|
||||
|
||||
item = WMAddSortedListItem(bPtr->columns[column], text);
|
||||
item->isBranch = isBranch;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMListItem*
|
||||
WMInsertBrowserItem(WMBrowser *bPtr, int column, int row, char *text,
|
||||
Bool isBranch)
|
||||
{
|
||||
WMListItem *item;
|
||||
|
||||
if (column < 0 || column >= bPtr->columnCount)
|
||||
return NULL;
|
||||
|
||||
item = WMInsertListItem(bPtr->columns[column], row, text);
|
||||
item->isBranch = isBranch;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
resizeBrowser(WMWidget *w, unsigned int width, unsigned int height)
|
||||
{
|
||||
WMBrowser *bPtr = (WMBrowser*)w;
|
||||
int cols = bPtr->maxVisibleColumns;
|
||||
int colX, colY;
|
||||
int i;
|
||||
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
|
||||
bPtr->columnSize.width = (width-(cols-1)*COLUMN_SPACING) / cols;
|
||||
bPtr->columnSize.height = height;
|
||||
|
||||
if (bPtr->flags.isTitled) {
|
||||
bPtr->columnSize.height -= TITLE_SPACING + bPtr->titleHeight;
|
||||
colY = TITLE_SPACING + bPtr->titleHeight;
|
||||
} else {
|
||||
colY = 0;
|
||||
}
|
||||
|
||||
if (bPtr->flags.hasScroller) {
|
||||
bPtr->columnSize.height -= SCROLLER_WIDTH + 4;
|
||||
|
||||
if (bPtr->scroller) {
|
||||
WMResizeWidget(bPtr->scroller, width-2, 1);
|
||||
WMMoveWidget(bPtr->scroller, 1, height-SCROLLER_WIDTH-1);
|
||||
}
|
||||
}
|
||||
|
||||
colX = 0;
|
||||
for (i = 0; i < bPtr->columnCount; i++) {
|
||||
WMResizeWidget(bPtr->columns[i], bPtr->columnSize.width,
|
||||
bPtr->columnSize.height);
|
||||
|
||||
WMMoveWidget(bPtr->columns[i], colX, colY);
|
||||
|
||||
if (COLUMN_IS_VISIBLE(bPtr, i)) {
|
||||
colX += bPtr->columnSize.width+COLUMN_SPACING;
|
||||
}
|
||||
}
|
||||
|
||||
W_ResizeView(bPtr->view, width, height);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintItem(WMList *lPtr, Drawable d, char *text, int state, WMRect *rect)
|
||||
{
|
||||
WMView *view = W_VIEW(lPtr);
|
||||
W_Screen *scr = view->screen;
|
||||
int width, height, x, y;
|
||||
|
||||
width = rect->size.width;
|
||||
height = rect->size.height;
|
||||
x = rect->pos.x;
|
||||
y = rect->pos.y;
|
||||
|
||||
if (state & WLDSSelected)
|
||||
XFillRectangle(scr->display, d, W_GC(scr->white), x, y,
|
||||
width, height);
|
||||
else
|
||||
XClearArea(scr->display, d, x, y, width, height, False);
|
||||
|
||||
W_PaintText(view, d, scr->normalFont, x+4, y, width,
|
||||
WALeft, W_GC(scr->black), False, text, strlen(text));
|
||||
|
||||
if (state & WLDSIsBranch) {
|
||||
XDrawLine(scr->display, d, W_GC(scr->darkGray), x+width-11, y+3,
|
||||
x+width-6, y+height/2);
|
||||
if (state & WLDSSelected)
|
||||
XDrawLine(scr->display, d,W_GC(scr->gray), x+width-11, y+height-5,
|
||||
x+width-6, y+height/2);
|
||||
else
|
||||
XDrawLine(scr->display, d,W_GC(scr->white), x+width-11, y+height-5,
|
||||
x+width-6, y+height/2);
|
||||
XDrawLine(scr->display, d, W_GC(scr->black), x+width-12, y+3,
|
||||
x+width-12, y+height-5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scrollCallback(WMWidget *scroller, void *self)
|
||||
{
|
||||
WMBrowser *bPtr = (WMBrowser*)self;
|
||||
WMScroller *sPtr = (WMScroller*)scroller;
|
||||
int newFirst;
|
||||
#define LAST_VISIBLE_COLUMN bPtr->firstVisibleColumn+bPtr->maxVisibleColumns
|
||||
|
||||
switch (WMGetScrollerHitPart(sPtr)) {
|
||||
case WSDecrementLine:
|
||||
if (bPtr->firstVisibleColumn > 0) {
|
||||
scrollToColumn(bPtr, bPtr->firstVisibleColumn-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case WSDecrementPage:
|
||||
if (bPtr->firstVisibleColumn > 0) {
|
||||
newFirst = bPtr->firstVisibleColumn - bPtr->maxVisibleColumns;
|
||||
|
||||
scrollToColumn(bPtr, newFirst);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case WSIncrementLine:
|
||||
if (LAST_VISIBLE_COLUMN < bPtr->columnCount) {
|
||||
scrollToColumn(bPtr, bPtr->firstVisibleColumn+1);
|
||||
}
|
||||
break;
|
||||
|
||||
case WSIncrementPage:
|
||||
if (LAST_VISIBLE_COLUMN < bPtr->columnCount) {
|
||||
newFirst = bPtr->firstVisibleColumn + bPtr->maxVisibleColumns;
|
||||
|
||||
if (newFirst+bPtr->maxVisibleColumns >= bPtr->columnCount)
|
||||
newFirst = bPtr->columnCount - bPtr->maxVisibleColumns;
|
||||
|
||||
scrollToColumn(bPtr, newFirst);
|
||||
}
|
||||
break;
|
||||
|
||||
case WSKnob:
|
||||
{
|
||||
float floatValue;
|
||||
float value = bPtr->columnCount - bPtr->maxVisibleColumns;
|
||||
|
||||
floatValue = WMGetScrollerValue(bPtr->scroller);
|
||||
|
||||
floatValue = (floatValue*value)/value;
|
||||
|
||||
newFirst = floatValue*(float)(bPtr->columnCount - bPtr->maxVisibleColumns);
|
||||
|
||||
if (bPtr->firstVisibleColumn != newFirst)
|
||||
scrollToColumn(bPtr, newFirst);
|
||||
else
|
||||
WMSetScrollerParameters(bPtr->scroller, floatValue,
|
||||
bPtr->maxVisibleColumns/(float)bPtr->columnCount);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case WSKnobSlot:
|
||||
case WSNoPart:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
#undef LAST_VISIBLE_COLUMN
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
setupScroller(WMBrowser *bPtr)
|
||||
{
|
||||
WMScroller *sPtr;
|
||||
int y;
|
||||
|
||||
y = bPtr->view->size.height - SCROLLER_WIDTH - 1;
|
||||
|
||||
sPtr = WMCreateScroller(bPtr);
|
||||
WMSetScrollerAction(sPtr, scrollCallback, bPtr);
|
||||
WMMoveWidget(sPtr, 1, y);
|
||||
WMResizeWidget(sPtr, bPtr->view->size.width-2, SCROLLER_WIDTH);
|
||||
|
||||
bPtr->scroller = sPtr;
|
||||
|
||||
WMMapWidget(sPtr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetBrowserAction(WMBrowser *bPtr, WMAction *action, void *clientData)
|
||||
{
|
||||
bPtr->action = action;
|
||||
bPtr->clientData = clientData;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetBrowserHasScroller(WMBrowser *bPtr, int hasScroller)
|
||||
{
|
||||
bPtr->flags.hasScroller = hasScroller;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Bool
|
||||
WMSetBrowserPath(WMBrowser *bPtr, char *path)
|
||||
{
|
||||
int i;
|
||||
char *str = wstrdup(path);
|
||||
char *tmp;
|
||||
int item;
|
||||
Bool ok = True;
|
||||
WMListItem *listItem;
|
||||
|
||||
removeColumn(bPtr, 1);
|
||||
|
||||
i = 0;
|
||||
tmp = strtok(str, bPtr->pathSeparator);
|
||||
while (tmp) {
|
||||
/* select it in the column */
|
||||
item = WMFindRowOfListItemWithTitle(bPtr->columns[i], tmp);
|
||||
if (item<0) {
|
||||
ok = False;
|
||||
break;
|
||||
}
|
||||
WMSelectListItem(bPtr->columns[i], item);
|
||||
WMSetListPosition(bPtr->columns[i], item);
|
||||
|
||||
listItem = WMGetListItem(bPtr->columns[i], item);
|
||||
if (!listItem || !listItem->isBranch) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* load next column */
|
||||
WMAddBrowserColumn(bPtr);
|
||||
|
||||
loadColumn(bPtr, i+1);
|
||||
|
||||
tmp = strtok(NULL, bPtr->pathSeparator);
|
||||
|
||||
i++;
|
||||
}
|
||||
free(str);
|
||||
|
||||
bPtr->selectedColumn = bPtr->usedColumnCount - 1;
|
||||
|
||||
scrollToColumn(bPtr, bPtr->columnCount-bPtr->maxVisibleColumns);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMGetBrowserPath(WMBrowser *bPtr)
|
||||
{
|
||||
return WMGetBrowserPathToColumn(bPtr, bPtr->columnCount);
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMGetBrowserPathToColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
int i, size;
|
||||
char *path;
|
||||
WMListItem *item;
|
||||
|
||||
if (column >= bPtr->usedColumnCount)
|
||||
column = bPtr->usedColumnCount-1;
|
||||
|
||||
/* calculate size of buffer */
|
||||
size = 0;
|
||||
for (i = 0; i <= column; i++) {
|
||||
item = WMGetListSelectedItem(bPtr->columns[i]);
|
||||
if (!item)
|
||||
break;
|
||||
size += strlen(item->text);
|
||||
}
|
||||
|
||||
/* get the path */
|
||||
path = wmalloc(size+(column+1)*strlen(bPtr->pathSeparator)+1);
|
||||
/* ignore first / */
|
||||
*path = 0;
|
||||
for (i = 0; i <= column; i++) {
|
||||
strcat(path, bPtr->pathSeparator);
|
||||
item = WMGetListSelectedItem(bPtr->columns[i]);
|
||||
if (!item)
|
||||
break;
|
||||
strcat(path, item->text);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
loadColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
assert(bPtr->fillColumn);
|
||||
|
||||
bPtr->flags.loadingColumn = 1;
|
||||
(*bPtr->fillColumn)(bPtr, column);
|
||||
bPtr->flags.loadingColumn = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintBrowser(WMBrowser *bPtr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!bPtr->view->flags.mapped)
|
||||
return;
|
||||
|
||||
W_DrawRelief(bPtr->view->screen, bPtr->view->window, 0,
|
||||
bPtr->view->size.height-SCROLLER_WIDTH-2,
|
||||
bPtr->view->size.width, 22, WRSunken);
|
||||
|
||||
if (bPtr->flags.isTitled) {
|
||||
for (i=0; i<bPtr->maxVisibleColumns; i++) {
|
||||
drawTitleOfColumn(bPtr, i+bPtr->firstVisibleColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
WMBrowser *bPtr = (WMBrowser*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_Browser);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
paintBrowser(bPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyBrowser(bPtr);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
scrollToColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
int i;
|
||||
int x;
|
||||
int notify = 0;
|
||||
|
||||
|
||||
if (column != bPtr->firstVisibleColumn)
|
||||
notify = 1;
|
||||
|
||||
if (column < 0)
|
||||
column = 0;
|
||||
|
||||
x = 0;
|
||||
bPtr->firstVisibleColumn = column;
|
||||
for (i = 0; i < bPtr->usedColumnCount; i++) {
|
||||
if (COLUMN_IS_VISIBLE(bPtr, i)) {
|
||||
WMMoveWidget(bPtr->columns[i], x,
|
||||
WMWidgetView(bPtr->columns[i])->pos.y);
|
||||
if (!WMWidgetView(bPtr->columns[i])->flags.realized)
|
||||
WMRealizeWidget(bPtr->columns[i]);
|
||||
WMMapWidget(bPtr->columns[i]);
|
||||
x += bPtr->columnSize.width+COLUMN_SPACING;
|
||||
} else {
|
||||
WMUnmapWidget(bPtr->columns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* update the scroller */
|
||||
if (bPtr->columnCount > bPtr->maxVisibleColumns) {
|
||||
float value, proportion;
|
||||
|
||||
value = bPtr->firstVisibleColumn
|
||||
/(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
|
||||
proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
|
||||
WMSetScrollerParameters(bPtr->scroller, value, proportion);
|
||||
} else {
|
||||
WMSetScrollerParameters(bPtr->scroller, 0, 1);
|
||||
}
|
||||
|
||||
if (bPtr->view->flags.mapped)
|
||||
paintBrowser(bPtr);
|
||||
|
||||
if (notify)
|
||||
WMPostNotificationName(WMBrowserDidScrollNotification, bPtr, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
listCallback(void *self, void *clientData)
|
||||
{
|
||||
WMBrowser *bPtr = (WMBrowser*)clientData;
|
||||
WMList *lPtr = (WMList*)self;
|
||||
WMListItem *item;
|
||||
int i;
|
||||
|
||||
item = WMGetListSelectedItem(lPtr);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
for (i=0; i<bPtr->columnCount; i++) {
|
||||
if (lPtr == bPtr->columns[i])
|
||||
break;
|
||||
}
|
||||
assert(i<bPtr->columnCount);
|
||||
|
||||
bPtr->selectedColumn = i;
|
||||
|
||||
/* columns at right must be cleared */
|
||||
removeColumn(bPtr, i+1);
|
||||
/* open directory */
|
||||
if (item->isBranch) {
|
||||
WMAddBrowserColumn(bPtr);
|
||||
loadColumn(bPtr, bPtr->usedColumnCount-1);
|
||||
}
|
||||
if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
|
||||
i = 0;
|
||||
else
|
||||
i = bPtr->usedColumnCount-bPtr->maxVisibleColumns;
|
||||
scrollToColumn(bPtr, i);
|
||||
|
||||
/* call callback for click */
|
||||
if (bPtr->action)
|
||||
(*bPtr->action)(bPtr, bPtr->clientData);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMLoadBrowserColumnZero(WMBrowser *bPtr)
|
||||
{
|
||||
if (!bPtr->flags.loaded) {
|
||||
/* create column 0 */
|
||||
WMAddBrowserColumn(bPtr);
|
||||
|
||||
loadColumn(bPtr, 0);
|
||||
|
||||
/* make column 0 visible */
|
||||
scrollToColumn(bPtr, 0);
|
||||
|
||||
bPtr->flags.loaded = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMRemoveBrowserItem(WMBrowser *bPtr, int column, int row)
|
||||
{
|
||||
WMList *list;
|
||||
|
||||
if (column < 0 || column >= bPtr->usedColumnCount)
|
||||
return;
|
||||
|
||||
list = WMGetBrowserListInColumn(bPtr, column);
|
||||
|
||||
if (row < 0 || row >= WMGetListNumberOfRows(list))
|
||||
return;
|
||||
|
||||
removeColumn(bPtr, column+1);
|
||||
if (bPtr->usedColumnCount < bPtr->maxVisibleColumns)
|
||||
scrollToColumn(bPtr, 0);
|
||||
else
|
||||
scrollToColumn(bPtr, bPtr->usedColumnCount-bPtr->maxVisibleColumns);
|
||||
|
||||
WMRemoveListItem(list, row);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMAddBrowserColumn(WMBrowser *bPtr)
|
||||
{
|
||||
WMList *list;
|
||||
WMList **clist;
|
||||
char **tlist;
|
||||
int colY;
|
||||
int index;
|
||||
|
||||
|
||||
if (bPtr->usedColumnCount < bPtr->columnCount) {
|
||||
return bPtr->usedColumnCount++;
|
||||
}
|
||||
|
||||
bPtr->usedColumnCount++;
|
||||
|
||||
if (bPtr->flags.isTitled) {
|
||||
colY = TITLE_SPACING + bPtr->titleHeight;
|
||||
} else {
|
||||
colY = 0;
|
||||
}
|
||||
|
||||
index = bPtr->columnCount;
|
||||
bPtr->columnCount++;
|
||||
clist = wmalloc(sizeof(WMList*)*bPtr->columnCount);
|
||||
tlist = wmalloc(sizeof(char*)*bPtr->columnCount);
|
||||
memcpy(clist, bPtr->columns, sizeof(WMList*)*(bPtr->columnCount-1));
|
||||
memcpy(tlist, bPtr->titles, sizeof(char*)*(bPtr->columnCount-1));
|
||||
if (bPtr->columns)
|
||||
free(bPtr->columns);
|
||||
if (bPtr->titles)
|
||||
free(bPtr->titles);
|
||||
bPtr->columns = clist;
|
||||
bPtr->titles = tlist;
|
||||
|
||||
bPtr->titles[index] = NULL;
|
||||
|
||||
list = WMCreateList(bPtr);
|
||||
WMSetListAction(list, listCallback, bPtr);
|
||||
WMSetListUserDrawProc(list, paintItem);
|
||||
bPtr->columns[index] = list;
|
||||
|
||||
WMResizeWidget(list, bPtr->columnSize.width, bPtr->columnSize.height);
|
||||
WMMoveWidget(list, (bPtr->columnSize.width+COLUMN_SPACING)*index, colY);
|
||||
if (COLUMN_IS_VISIBLE(bPtr, index))
|
||||
WMMapWidget(list);
|
||||
|
||||
/* update the scroller */
|
||||
if (bPtr->columnCount > bPtr->maxVisibleColumns) {
|
||||
float value, proportion;
|
||||
|
||||
value = bPtr->firstVisibleColumn
|
||||
/(float)(bPtr->columnCount-bPtr->maxVisibleColumns);
|
||||
proportion = bPtr->maxVisibleColumns/(float)bPtr->columnCount;
|
||||
WMSetScrollerParameters(bPtr->scroller, value, proportion);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroyBrowser(WMBrowser *bPtr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<bPtr->columnCount; i++) {
|
||||
if (bPtr->titles[i])
|
||||
free(bPtr->titles[i]);
|
||||
}
|
||||
free(bPtr->titles);
|
||||
|
||||
free(bPtr->pathSeparator);
|
||||
|
||||
free(bPtr);
|
||||
}
|
||||
|
||||
|
||||
714
WINGs/wbutton.c
Normal file
714
WINGs/wbutton.c
Normal file
@@ -0,0 +1,714 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
typedef struct W_Button {
|
||||
W_Class widgetClass;
|
||||
WMView *view;
|
||||
|
||||
char *caption;
|
||||
|
||||
char *altCaption;
|
||||
|
||||
WMFont *font;
|
||||
|
||||
W_Pixmap *image;
|
||||
W_Pixmap *altImage;
|
||||
|
||||
void *clientData;
|
||||
WMAction *action;
|
||||
|
||||
int tag;
|
||||
|
||||
int groupIndex;
|
||||
|
||||
float periodicDelay;
|
||||
float periodicInterval;
|
||||
|
||||
WMHandlerID *timer; /* for continuous mode */
|
||||
|
||||
struct {
|
||||
WMButtonType type:4;
|
||||
WMImagePosition imagePosition:4;
|
||||
WMAlignment alignment:2;
|
||||
|
||||
unsigned int selected:1;
|
||||
|
||||
unsigned int enabled:1;
|
||||
|
||||
unsigned int bordered:1;
|
||||
|
||||
unsigned int springLoaded:1;
|
||||
|
||||
unsigned int pushIn:1; /* change relief while pushed */
|
||||
|
||||
unsigned int pushLight:1; /* highlight while pushed */
|
||||
|
||||
unsigned int pushChange:1; /* change caption while pushed */
|
||||
|
||||
unsigned int stateLight:1; /* state indicated by highlight */
|
||||
|
||||
unsigned int stateChange:1; /* state indicated by caption change */
|
||||
|
||||
unsigned int statePush:1; /* state indicated by relief */
|
||||
|
||||
unsigned int continuous:1; /* continually perform action */
|
||||
/* */
|
||||
unsigned int prevSelected:1;
|
||||
|
||||
unsigned int pushed:1;
|
||||
|
||||
unsigned int wasPushed:1;
|
||||
|
||||
unsigned int redrawPending:1;
|
||||
|
||||
unsigned int addedObserver:1;
|
||||
} flags;
|
||||
} Button;
|
||||
|
||||
|
||||
|
||||
#define DEFAULT_BUTTON_WIDTH 60
|
||||
#define DEFAULT_BUTTON_HEIGHT 24
|
||||
#define DEFAULT_BUTTON_ALIGNMENT WACenter
|
||||
#define DEFAULT_BUTTON_IS_BORDERED True
|
||||
|
||||
|
||||
#define DEFAULT_RADIO_WIDTH 100
|
||||
#define DEFAULT_RADIO_HEIGHT 20
|
||||
#define DEFAULT_RADIO_ALIGNMENT WALeft
|
||||
#define DEFAULT_RADIO_IMAGE_POSITION WIPLeft
|
||||
#define DEFAULT_RADIO_TEXT "Radio"
|
||||
|
||||
|
||||
#define DEFAULT_SWITCH_WIDTH 100
|
||||
#define DEFAULT_SWITCH_HEIGHT 20
|
||||
#define DEFAULT_SWITCH_ALIGNMENT WALeft
|
||||
#define DEFAULT_SWITCH_IMAGE_POSITION WIPLeft
|
||||
#define DEFAULT_SWITCH_TEXT "Switch"
|
||||
|
||||
|
||||
static void destroyButton(Button *bPtr);
|
||||
static void paintButton(Button *bPtr);
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleActionEvents(XEvent *event, void *data);
|
||||
|
||||
|
||||
W_ViewProcedureTable _ButtonViewProcedures = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static char *WMPushedRadioNotification="WMPushedRadioNotification";
|
||||
|
||||
|
||||
#define NFONT(b) (b)->view->screen->normalFont
|
||||
|
||||
|
||||
WMButton*
|
||||
WMCreateCustomButton(WMWidget *parent, int behaviourMask)
|
||||
{
|
||||
Button *bPtr;
|
||||
|
||||
bPtr = wmalloc(sizeof(Button));
|
||||
memset(bPtr, 0, sizeof(Button));
|
||||
|
||||
bPtr->widgetClass = WC_Button;
|
||||
|
||||
bPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!bPtr->view) {
|
||||
free(bPtr);
|
||||
return NULL;
|
||||
}
|
||||
bPtr->view->self = bPtr;
|
||||
|
||||
bPtr->flags.type = 0;
|
||||
|
||||
bPtr->flags.springLoaded = (behaviourMask & WBBSpringLoadedMask)!=0;
|
||||
bPtr->flags.pushIn = (behaviourMask & WBBPushInMask)!=0;
|
||||
bPtr->flags.pushChange = (behaviourMask & WBBPushChangeMask)!=0;
|
||||
bPtr->flags.pushLight = (behaviourMask & WBBPushLightMask)!=0;
|
||||
bPtr->flags.stateLight = (behaviourMask & WBBStateLightMask)!=0;
|
||||
bPtr->flags.stateChange = (behaviourMask & WBBStateChangeMask)!=0;
|
||||
bPtr->flags.statePush = (behaviourMask & WBBStatePushMask)!=0;
|
||||
|
||||
W_ResizeView(bPtr->view, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT);
|
||||
bPtr->flags.alignment = DEFAULT_BUTTON_ALIGNMENT;
|
||||
bPtr->flags.bordered = DEFAULT_BUTTON_IS_BORDERED;
|
||||
|
||||
bPtr->flags.enabled = 1;
|
||||
|
||||
|
||||
WMCreateEventHandler(bPtr->view, ExposureMask|StructureNotifyMask,
|
||||
handleEvents, bPtr);
|
||||
|
||||
WMCreateEventHandler(bPtr->view, ButtonPressMask|ButtonReleaseMask
|
||||
|EnterWindowMask|LeaveWindowMask,
|
||||
handleActionEvents, bPtr);
|
||||
|
||||
W_ResizeView(bPtr->view, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT);
|
||||
bPtr->flags.alignment = DEFAULT_BUTTON_ALIGNMENT;
|
||||
bPtr->flags.bordered = DEFAULT_BUTTON_IS_BORDERED;
|
||||
|
||||
return bPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMButton*
|
||||
WMCreateButton(WMWidget *parent, WMButtonType type)
|
||||
{
|
||||
W_Screen *scrPtr = W_VIEW(parent)->screen;
|
||||
Button *bPtr;
|
||||
|
||||
switch (type) {
|
||||
case WBTMomentaryPush:
|
||||
bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask
|
||||
|WBBPushInMask|WBBPushLightMask);
|
||||
break;
|
||||
|
||||
case WBTMomentaryChange:
|
||||
bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask
|
||||
|WBBPushChangeMask);
|
||||
break;
|
||||
|
||||
case WBTPushOnPushOff:
|
||||
bPtr = WMCreateCustomButton(parent, WBBPushInMask|WBBStatePushMask
|
||||
|WBBStateLightMask);
|
||||
break;
|
||||
|
||||
case WBTToggle:
|
||||
bPtr = WMCreateCustomButton(parent, WBBPushInMask|WBBStateChangeMask
|
||||
|WBBStatePushMask);
|
||||
break;
|
||||
|
||||
case WBTOnOff:
|
||||
bPtr = WMCreateCustomButton(parent, WBBStateLightMask);
|
||||
break;
|
||||
|
||||
case WBTSwitch:
|
||||
bPtr = WMCreateCustomButton(parent, WBBStateChangeMask);
|
||||
bPtr->flags.bordered = 0;
|
||||
bPtr->image = WMRetainPixmap(scrPtr->checkButtonImageOff);
|
||||
bPtr->altImage = WMRetainPixmap(scrPtr->checkButtonImageOn);
|
||||
break;
|
||||
|
||||
case WBTRadio:
|
||||
bPtr = WMCreateCustomButton(parent, WBBStateChangeMask);
|
||||
bPtr->flags.bordered = 0;
|
||||
bPtr->image = WMRetainPixmap(scrPtr->radioButtonImageOff);
|
||||
bPtr->altImage = WMRetainPixmap(scrPtr->radioButtonImageOn);
|
||||
break;
|
||||
|
||||
default:
|
||||
case WBTMomentaryLight:
|
||||
bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask
|
||||
|WBBPushLightMask);
|
||||
bPtr->flags.bordered = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
bPtr->flags.type = type;
|
||||
|
||||
if (type==WBTRadio) {
|
||||
W_ResizeView(bPtr->view, DEFAULT_RADIO_WIDTH, DEFAULT_RADIO_HEIGHT);
|
||||
WMSetButtonText(bPtr, DEFAULT_RADIO_TEXT);
|
||||
bPtr->flags.alignment = DEFAULT_RADIO_ALIGNMENT;
|
||||
bPtr->flags.imagePosition = DEFAULT_RADIO_IMAGE_POSITION;
|
||||
} else if (type==WBTSwitch) {
|
||||
W_ResizeView(bPtr->view, DEFAULT_SWITCH_WIDTH, DEFAULT_SWITCH_HEIGHT);
|
||||
WMSetButtonText(bPtr, DEFAULT_SWITCH_TEXT);
|
||||
bPtr->flags.alignment = DEFAULT_SWITCH_ALIGNMENT;
|
||||
bPtr->flags.imagePosition = DEFAULT_SWITCH_IMAGE_POSITION;
|
||||
}
|
||||
|
||||
return bPtr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonImage(WMButton *bPtr, WMPixmap *image)
|
||||
{
|
||||
if (bPtr->image!=NULL)
|
||||
WMReleasePixmap(bPtr->image);
|
||||
bPtr->image = WMRetainPixmap(image);
|
||||
|
||||
|
||||
if (bPtr->view->flags.realized) {
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonAltImage(WMButton *bPtr, WMPixmap *image)
|
||||
{
|
||||
if (bPtr->altImage!=NULL)
|
||||
WMReleasePixmap(bPtr->altImage);
|
||||
bPtr->altImage = WMRetainPixmap(image);
|
||||
|
||||
|
||||
if (bPtr->view->flags.realized) {
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonImagePosition(WMButton *bPtr, WMImagePosition position)
|
||||
{
|
||||
bPtr->flags.imagePosition = position;
|
||||
|
||||
|
||||
if (bPtr->view->flags.realized) {
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonTextAlignment(WMButton *bPtr, WMAlignment alignment)
|
||||
{
|
||||
bPtr->flags.alignment = alignment;
|
||||
|
||||
|
||||
if (bPtr->view->flags.realized) {
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WMSetButtonText(WMButton *bPtr, char *text)
|
||||
{
|
||||
if (bPtr->caption)
|
||||
free(bPtr->caption);
|
||||
|
||||
if (text!=NULL) {
|
||||
bPtr->caption = wstrdup(text);
|
||||
} else {
|
||||
bPtr->caption = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (bPtr->view->flags.realized) {
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonAltText(WMButton *bPtr, char *text)
|
||||
{
|
||||
if (bPtr->altCaption)
|
||||
free(bPtr->altCaption);
|
||||
|
||||
if (text!=NULL) {
|
||||
bPtr->altCaption = wstrdup(text);
|
||||
} else {
|
||||
bPtr->altCaption = NULL;
|
||||
}
|
||||
|
||||
if (bPtr->view->flags.realized) {
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonSelected(WMButton *bPtr, int isSelected)
|
||||
{
|
||||
bPtr->flags.selected = isSelected;
|
||||
|
||||
if (bPtr->view->flags.realized) {
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetButtonSelected(WMButton *bPtr)
|
||||
{
|
||||
CHECK_CLASS(bPtr, WC_Button);
|
||||
|
||||
return bPtr->flags.selected;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonBordered(WMButton *bPtr, int isBordered)
|
||||
{
|
||||
bPtr->flags.bordered = isBordered;
|
||||
|
||||
if (bPtr->view->flags.realized) {
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonFont(WMButton *bPtr, WMFont *font)
|
||||
{
|
||||
if (bPtr->font)
|
||||
WMReleaseFont(bPtr->font);
|
||||
|
||||
bPtr->font = WMRetainFont(font);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonEnabled(WMButton *bPtr, Bool flag)
|
||||
{
|
||||
bPtr->flags.enabled = flag;
|
||||
|
||||
if (bPtr->view->flags.mapped) {
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonTag(WMButton *bPtr, int tag)
|
||||
{
|
||||
bPtr->tag = tag;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMPerformButtonClick(WMButton *bPtr)
|
||||
{
|
||||
CHECK_CLASS(bPtr, WC_Button);
|
||||
|
||||
if (!bPtr->flags.enabled)
|
||||
return;
|
||||
|
||||
bPtr->flags.pushed = 1;
|
||||
bPtr->flags.selected = 1;
|
||||
|
||||
if (bPtr->view->flags.mapped) {
|
||||
paintButton(bPtr);
|
||||
XFlush(WMScreenDisplay(WMWidgetScreen(bPtr)));
|
||||
wusleep(20000);
|
||||
}
|
||||
|
||||
if (bPtr->groupIndex>0) {
|
||||
WMPostNotificationName(WMPushedRadioNotification, bPtr, NULL);
|
||||
}
|
||||
|
||||
if (bPtr->action)
|
||||
(*bPtr->action)(bPtr, bPtr->clientData);
|
||||
|
||||
bPtr->flags.pushed = 0;
|
||||
|
||||
if (bPtr->view->flags.mapped)
|
||||
paintButton(bPtr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonAction(WMButton *bPtr, WMAction *action, void *clientData)
|
||||
{
|
||||
CHECK_CLASS(bPtr, WC_Button);
|
||||
|
||||
bPtr->action = action;
|
||||
|
||||
bPtr->clientData = clientData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
radioPushObserver(void *observerData, WMNotification *notification)
|
||||
{
|
||||
WMButton *bPtr = (WMButton*)observerData;
|
||||
WMButton *pushedButton = (WMButton*)WMGetNotificationObject(notification);
|
||||
|
||||
if (bPtr!=pushedButton && pushedButton->groupIndex == bPtr->groupIndex
|
||||
&& bPtr->groupIndex!=0) {
|
||||
if (bPtr->flags.selected) {
|
||||
bPtr->flags.selected = 0;
|
||||
paintButton(bPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMGroupButtons(WMButton *bPtr, WMButton *newMember)
|
||||
{
|
||||
static int tagIndex = 0;
|
||||
|
||||
CHECK_CLASS(bPtr, WC_Button);
|
||||
CHECK_CLASS(newMember, WC_Button);
|
||||
|
||||
if (!bPtr->flags.addedObserver) {
|
||||
WMAddNotificationObserver(radioPushObserver, bPtr,
|
||||
WMPushedRadioNotification, NULL);
|
||||
bPtr->flags.addedObserver = 1;
|
||||
}
|
||||
if (!newMember->flags.addedObserver) {
|
||||
WMAddNotificationObserver(radioPushObserver, newMember,
|
||||
WMPushedRadioNotification, NULL);
|
||||
newMember->flags.addedObserver = 1;
|
||||
}
|
||||
|
||||
if (bPtr->groupIndex==0) {
|
||||
bPtr->groupIndex = ++tagIndex;
|
||||
}
|
||||
newMember->groupIndex = bPtr->groupIndex;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonContinuous(WMButton *bPtr, Bool flag)
|
||||
{
|
||||
bPtr->flags.continuous = flag;
|
||||
if (bPtr->timer) {
|
||||
WMDeleteTimerHandler(bPtr->timer);
|
||||
bPtr->timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetButtonPeriodicDelay(WMButton *bPtr, float delay, float interval)
|
||||
{
|
||||
bPtr->periodicInterval = interval;
|
||||
bPtr->periodicDelay = delay;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
paintButton(Button *bPtr)
|
||||
{
|
||||
W_Screen *scrPtr = bPtr->view->screen;
|
||||
GC gc;
|
||||
WMReliefType relief;
|
||||
int offset;
|
||||
char *caption;
|
||||
WMPixmap *image;
|
||||
GC textGC;
|
||||
|
||||
gc = NULL;
|
||||
caption = bPtr->caption;
|
||||
image = bPtr->image;
|
||||
offset = 0;
|
||||
if (bPtr->flags.bordered)
|
||||
relief = WRRaised;
|
||||
else
|
||||
relief = WRFlat;
|
||||
|
||||
if (bPtr->flags.selected) {
|
||||
if (bPtr->flags.stateLight)
|
||||
gc = W_GC(scrPtr->white);
|
||||
|
||||
if (bPtr->flags.stateChange) {
|
||||
if (bPtr->altCaption) {
|
||||
caption = bPtr->altCaption;
|
||||
}
|
||||
if (bPtr->altImage)
|
||||
image = bPtr->altImage;
|
||||
}
|
||||
|
||||
if (bPtr->flags.statePush && bPtr->flags.bordered) {
|
||||
relief = WRSunken;
|
||||
offset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bPtr->flags.pushed) {
|
||||
if (bPtr->flags.pushIn) {
|
||||
relief = WRPushed;
|
||||
offset = 1;
|
||||
}
|
||||
if (bPtr->flags.pushLight)
|
||||
gc = W_GC(scrPtr->white);
|
||||
|
||||
if (bPtr->flags.pushChange) {
|
||||
if (bPtr->altCaption) {
|
||||
caption = bPtr->altCaption;
|
||||
}
|
||||
if (bPtr->altImage)
|
||||
image = bPtr->altImage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (bPtr->flags.enabled)
|
||||
textGC = W_GC(scrPtr->black);
|
||||
else
|
||||
textGC = W_GC(scrPtr->darkGray);
|
||||
|
||||
W_PaintTextAndImage(bPtr->view, True, textGC,
|
||||
(bPtr->font!=NULL ? bPtr->font : scrPtr->normalFont),
|
||||
relief, caption, bPtr->flags.alignment, image,
|
||||
bPtr->flags.imagePosition, gc, offset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
Button *bPtr = (Button*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_Button);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintButton(bPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyButton(bPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
autoRepeat(void *data)
|
||||
{
|
||||
Button *bPtr = (Button*)data;
|
||||
|
||||
if (bPtr->action && bPtr->flags.pushed)
|
||||
(*bPtr->action)(bPtr, bPtr->clientData);
|
||||
|
||||
bPtr->timer = WMAddTimerHandler((int)(bPtr->periodicInterval*1000),
|
||||
autoRepeat, bPtr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
Button *bPtr = (Button*)data;
|
||||
int doclick = 0, dopaint=0;
|
||||
|
||||
CHECK_CLASS(data, WC_Button);
|
||||
|
||||
if (!bPtr->flags.enabled)
|
||||
return;
|
||||
|
||||
switch (event->type) {
|
||||
case EnterNotify:
|
||||
if (bPtr->groupIndex == 0) {
|
||||
bPtr->flags.pushed = bPtr->flags.wasPushed;
|
||||
if (bPtr->flags.pushed) {
|
||||
bPtr->flags.selected = !bPtr->flags.prevSelected;
|
||||
dopaint = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LeaveNotify:
|
||||
if (bPtr->groupIndex == 0) {
|
||||
bPtr->flags.wasPushed = bPtr->flags.pushed;
|
||||
if (bPtr->flags.pushed) {
|
||||
bPtr->flags.selected = bPtr->flags.prevSelected;
|
||||
dopaint = 1;
|
||||
}
|
||||
bPtr->flags.pushed = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
if (event->xbutton.button == Button1) {
|
||||
if (bPtr->groupIndex>0) {
|
||||
if (!bPtr->flags.selected)
|
||||
doclick = 1;
|
||||
bPtr->flags.pushed = 1;
|
||||
bPtr->flags.selected = 1;
|
||||
dopaint = 1;
|
||||
break;
|
||||
}
|
||||
bPtr->flags.wasPushed = 0;
|
||||
bPtr->flags.pushed = 1;
|
||||
bPtr->flags.prevSelected = bPtr->flags.selected;
|
||||
bPtr->flags.selected = !bPtr->flags.selected;
|
||||
dopaint = 1;
|
||||
|
||||
if (bPtr->flags.continuous && !bPtr->timer) {
|
||||
bPtr->timer = WMAddTimerHandler((int)(bPtr->periodicDelay*1000),
|
||||
autoRepeat, bPtr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
if (event->xbutton.button == Button1) {
|
||||
if (bPtr->flags.pushed) {
|
||||
if (bPtr->groupIndex==0)
|
||||
doclick = 1;
|
||||
dopaint = 1;
|
||||
if (bPtr->flags.springLoaded) {
|
||||
bPtr->flags.selected = bPtr->flags.prevSelected;
|
||||
}
|
||||
}
|
||||
bPtr->flags.pushed = 0;
|
||||
}
|
||||
if (bPtr->timer) {
|
||||
WMDeleteTimerHandler(bPtr->timer);
|
||||
bPtr->timer = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (dopaint)
|
||||
paintButton(bPtr);
|
||||
|
||||
if (doclick) {
|
||||
if (bPtr->flags.selected && bPtr->groupIndex>0) {
|
||||
WMPostNotificationName(WMPushedRadioNotification, bPtr, NULL);
|
||||
}
|
||||
|
||||
if (bPtr->action)
|
||||
(*bPtr->action)(bPtr, bPtr->clientData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroyButton(Button *bPtr)
|
||||
{
|
||||
if (bPtr->flags.addedObserver) {
|
||||
WMRemoveNotificationObserver(bPtr);
|
||||
}
|
||||
|
||||
if (bPtr->timer)
|
||||
WMDeleteTimerHandler(bPtr->timer);
|
||||
|
||||
if (bPtr->font)
|
||||
WMReleaseFont(bPtr->font);
|
||||
|
||||
if (bPtr->caption)
|
||||
free(bPtr->caption);
|
||||
|
||||
if (bPtr->altCaption)
|
||||
free(bPtr->altCaption);
|
||||
|
||||
if (bPtr->image)
|
||||
WMReleasePixmap(bPtr->image);
|
||||
|
||||
if (bPtr->altImage)
|
||||
WMReleasePixmap(bPtr->altImage);
|
||||
|
||||
free(bPtr);
|
||||
}
|
||||
|
||||
|
||||
325
WINGs/wcolor.c
Normal file
325
WINGs/wcolor.c
Normal file
@@ -0,0 +1,325 @@
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <wraster.h>
|
||||
|
||||
#define LIGHT_STIPPLE_WIDTH 4
|
||||
#define LIGHT_STIPPLE_HEIGHT 4
|
||||
static unsigned char LIGHT_STIPPLE_BITS[] = {
|
||||
0x05, 0x0a, 0x05, 0x0a};
|
||||
|
||||
#define DARK_STIPPLE_WIDTH 4
|
||||
#define DARK_STIPPLE_HEIGHT 4
|
||||
static unsigned char DARK_STIPPLE_BITS[] = {
|
||||
0x0a, 0x04, 0x0a, 0x01};
|
||||
|
||||
|
||||
static WMColor *createRGBColor(WMScreen *scr, unsigned short red,
|
||||
unsigned short green, unsigned short blue);
|
||||
|
||||
/*
|
||||
* TODO: make the color creation code return the same WMColor for the
|
||||
* same colors.
|
||||
* make findCloseColor() find the closest color in the RContext pallette
|
||||
* or in the other colors allocated by WINGs.
|
||||
*/
|
||||
|
||||
static WMColor*
|
||||
findCloseColor(WMScreen *scr, unsigned short red, unsigned short green,
|
||||
unsigned short blue)
|
||||
{
|
||||
WMColor *color;
|
||||
XColor xcolor;
|
||||
RColor rcolor;
|
||||
XGCValues gcv;
|
||||
|
||||
rcolor.red = red>>8;
|
||||
rcolor.green = green>>8;
|
||||
rcolor.blue = blue>>8;
|
||||
|
||||
if (!RGetClosestXColor(scr->rcontext, &rcolor, &xcolor))
|
||||
return NULL;
|
||||
|
||||
if (!XAllocColor(scr->display, scr->colormap, &xcolor))
|
||||
return NULL;
|
||||
|
||||
color = wmalloc(sizeof(WMColor));
|
||||
|
||||
color->screen = scr;
|
||||
color->refCount = 1;
|
||||
color->color = xcolor;
|
||||
color->flags.exact = 1;
|
||||
|
||||
gcv.foreground = color->color.pixel;
|
||||
gcv.graphics_exposures = False;
|
||||
color->gc = XCreateGC(scr->display, scr->rcontext->drawable,
|
||||
GCForeground|GCGraphicsExposures, &gcv);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static WMColor*
|
||||
createRGBColor(WMScreen *scr, unsigned short red, unsigned short green,
|
||||
unsigned short blue)
|
||||
{
|
||||
WMColor *color;
|
||||
XGCValues gcv;
|
||||
XColor xcolor;
|
||||
|
||||
xcolor.red = red;
|
||||
xcolor.green = green;
|
||||
xcolor.blue = blue;
|
||||
xcolor.flags = DoRed|DoGreen|DoBlue;
|
||||
if (!XAllocColor(scr->display, scr->colormap, &xcolor))
|
||||
return NULL;
|
||||
|
||||
color = wmalloc(sizeof(WMColor));
|
||||
|
||||
color->screen = scr;
|
||||
color->refCount = 1;
|
||||
color->color = xcolor;
|
||||
color->flags.exact = 1;
|
||||
|
||||
gcv.foreground = color->color.pixel;
|
||||
gcv.graphics_exposures = False;
|
||||
color->gc = XCreateGC(scr->display, scr->rcontext->drawable,
|
||||
GCForeground|GCGraphicsExposures, &gcv);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMColor*
|
||||
WMCreateRGBColor(WMScreen *scr, unsigned short red, unsigned short green,
|
||||
unsigned short blue, Bool exact)
|
||||
{
|
||||
WMColor *color = NULL;
|
||||
|
||||
if (!exact || !(color=createRGBColor(scr, red, green, blue))) {
|
||||
color = findCloseColor(scr, red, green, blue);
|
||||
}
|
||||
if (!color)
|
||||
color = WMBlackColor(scr);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
WMColor*
|
||||
WMCreateNamedColor(WMScreen *scr, char *name, Bool exact)
|
||||
{
|
||||
WMColor *color;
|
||||
XColor xcolor;
|
||||
|
||||
if (!XParseColor(scr->display, scr->colormap, name, &xcolor))
|
||||
return NULL;
|
||||
|
||||
|
||||
if (!exact || !(color=createRGBColor(scr, xcolor.red, xcolor.green,
|
||||
xcolor.blue))) {
|
||||
color = findCloseColor(scr, xcolor.red, xcolor.green, xcolor.blue);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMColor*
|
||||
WMRetainColor(WMColor *color)
|
||||
{
|
||||
assert(color!=NULL);
|
||||
|
||||
color->refCount++;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMReleaseColor(WMColor *color)
|
||||
{
|
||||
color->refCount--;
|
||||
|
||||
if (color->refCount < 1) {
|
||||
XFreeColors(color->screen->display, color->screen->colormap,
|
||||
&(color->color.pixel), 1, 0);
|
||||
XFreeGC(color->screen->display, color->gc);
|
||||
free(color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMPaintColorSwatch(WMColor *color, Drawable d, int x, int y,
|
||||
unsigned int width, unsigned int height)
|
||||
{
|
||||
XFillRectangle(color->screen->display, d, color->gc, x, y, width, height);
|
||||
}
|
||||
|
||||
|
||||
WMPixel
|
||||
WMColorPixel(WMColor *color)
|
||||
{
|
||||
return color->color.pixel;
|
||||
}
|
||||
|
||||
|
||||
GC
|
||||
WMColorGC(WMColor *color)
|
||||
{
|
||||
return color->gc;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetColorInGC(WMColor *color, GC gc)
|
||||
{
|
||||
XSetForeground(color->screen->display, gc, color->color.pixel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* "system" colors */
|
||||
WMColor*
|
||||
WMWhiteColor(WMScreen *scr)
|
||||
{
|
||||
if (!scr->white) {
|
||||
scr->white = WMCreateRGBColor(scr, 0xffff, 0xffff, 0xffff, True);
|
||||
if (!scr->white->flags.exact)
|
||||
wwarning("could not allocate %s color", "white");
|
||||
}
|
||||
return WMRetainColor(scr->white);
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMColor*
|
||||
WMBlackColor(WMScreen *scr)
|
||||
{
|
||||
if (!scr->black) {
|
||||
scr->black = WMCreateRGBColor(scr, 0, 0, 0, True);
|
||||
if (!scr->black->flags.exact)
|
||||
wwarning("could not allocate %s color", "black");
|
||||
}
|
||||
return WMRetainColor(scr->black);
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMColor*
|
||||
WMGrayColor(WMScreen *scr)
|
||||
{
|
||||
if (!scr->gray) {
|
||||
WMColor *color;
|
||||
|
||||
if (scr->depth == 1) {
|
||||
Pixmap stipple;
|
||||
WMColor *white = WMWhiteColor(scr);
|
||||
WMColor *black = WMBlackColor(scr);
|
||||
XGCValues gcv;
|
||||
|
||||
stipple = XCreateBitmapFromData(scr->display, W_DRAWABLE(scr),
|
||||
LIGHT_STIPPLE_BITS, LIGHT_STIPPLE_WIDTH,
|
||||
LIGHT_STIPPLE_HEIGHT);
|
||||
|
||||
color = createRGBColor(scr, 0xffff, 0xffff, 0xffff);
|
||||
XFreeGC(scr->display, color->gc);
|
||||
|
||||
gcv.foreground = white->color.pixel;
|
||||
gcv.background = black->color.pixel;
|
||||
gcv.fill_style = FillStippled;
|
||||
gcv.stipple = stipple;
|
||||
color->gc = XCreateGC(scr->display, W_DRAWABLE(scr), GCForeground
|
||||
|GCBackground|GCStipple|GCFillStyle
|
||||
|GCGraphicsExposures, &gcv);
|
||||
|
||||
XFreePixmap(scr->display, stipple);
|
||||
WMReleaseColor(white);
|
||||
WMReleaseColor(black);
|
||||
} else {
|
||||
color = WMCreateRGBColor(scr, 0xaeba, 0xaaaa, 0xaeba, True);
|
||||
if (!color->flags.exact)
|
||||
wwarning("could not allocate %s color", "gray");
|
||||
}
|
||||
scr->gray = color;
|
||||
}
|
||||
return WMRetainColor(scr->gray);
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMColor*
|
||||
WMDarkGrayColor(WMScreen *scr)
|
||||
{
|
||||
if (!scr->darkGray) {
|
||||
WMColor *color;
|
||||
|
||||
if (scr->depth == 1) {
|
||||
Pixmap stipple;
|
||||
WMColor *white = WMWhiteColor(scr);
|
||||
WMColor *black = WMBlackColor(scr);
|
||||
XGCValues gcv;
|
||||
|
||||
stipple = XCreateBitmapFromData(scr->display, W_DRAWABLE(scr),
|
||||
DARK_STIPPLE_BITS, DARK_STIPPLE_WIDTH,
|
||||
DARK_STIPPLE_HEIGHT);
|
||||
|
||||
color = createRGBColor(scr, 0, 0, 0);
|
||||
XFreeGC(scr->display, color->gc);
|
||||
|
||||
gcv.foreground = white->color.pixel;
|
||||
gcv.background = black->color.pixel;
|
||||
gcv.fill_style = FillStippled;
|
||||
gcv.stipple = stipple;
|
||||
color->gc = XCreateGC(scr->display, W_DRAWABLE(scr), GCForeground
|
||||
|GCBackground|GCStipple|GCFillStyle
|
||||
|GCGraphicsExposures, &gcv);
|
||||
|
||||
XFreePixmap(scr->display, stipple);
|
||||
WMReleaseColor(white);
|
||||
WMReleaseColor(black);
|
||||
} else {
|
||||
color = WMCreateRGBColor(scr, 0x5144, 0x5555, 0x5144, True);
|
||||
if (!color->flags.exact)
|
||||
wwarning("could not allocate %s color", "dark gray");
|
||||
}
|
||||
scr->darkGray = color;
|
||||
}
|
||||
return WMRetainColor(scr->darkGray);
|
||||
}
|
||||
|
||||
|
||||
unsigned short
|
||||
WMRedComponentOfColor(WMColor *color)
|
||||
{
|
||||
return color->color.red;
|
||||
}
|
||||
|
||||
|
||||
unsigned short
|
||||
WMGreenComponentOfColor(WMColor *color)
|
||||
{
|
||||
return color->color.green;
|
||||
}
|
||||
|
||||
|
||||
unsigned short
|
||||
WMBlueComponentOfColor(WMColor *color)
|
||||
{
|
||||
return color->color.blue;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMGetColorRGBDescription(WMColor *color)
|
||||
{
|
||||
char *str = wmalloc(32);
|
||||
|
||||
sprintf(str, "rgb:%4x/%4x/%4x", color->color.red, color->color.green,
|
||||
color->color.blue);
|
||||
|
||||
return str;
|
||||
}
|
||||
257
WINGs/wcolorwell.c
Normal file
257
WINGs/wcolorwell.c
Normal file
@@ -0,0 +1,257 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
typedef struct W_ColorWell {
|
||||
W_Class widgetClass;
|
||||
WMView *view;
|
||||
|
||||
WMView *colorView;
|
||||
|
||||
WMColor *color;
|
||||
|
||||
WMAction *action;
|
||||
void *clientData;
|
||||
|
||||
WMPoint ipoint;
|
||||
|
||||
struct {
|
||||
unsigned int active:1;
|
||||
unsigned int bordered:1;
|
||||
} flags;
|
||||
} ColorWell;
|
||||
|
||||
|
||||
static void destroyColorWell(ColorWell *cPtr);
|
||||
static void paintColorWell(ColorWell *cPtr);
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
#if 0
|
||||
static void handleDragEvents(XEvent *event, void *data);
|
||||
#endif
|
||||
static void handleActionEvents(XEvent *event, void *data);
|
||||
|
||||
static void resizeColorWell();
|
||||
|
||||
W_ViewProcedureTable _ColorWellViewProcedures = {
|
||||
NULL,
|
||||
resizeColorWell,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
static WMDragSourceProcs dragProcs = {
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
#define DEFAULT_WIDTH 60
|
||||
#define DEFAULT_HEIGHT 30
|
||||
#define DEFAULT_BORDER_WIDTH 6
|
||||
|
||||
#define MIN_WIDTH 16
|
||||
#define MIN_HEIGHT 8
|
||||
|
||||
|
||||
|
||||
WMColorWell*
|
||||
WMCreateColorWell(WMWidget *parent)
|
||||
{
|
||||
ColorWell *cPtr;
|
||||
|
||||
cPtr = wmalloc(sizeof(ColorWell));
|
||||
memset(cPtr, 0, sizeof(ColorWell));
|
||||
|
||||
cPtr->widgetClass = WC_ColorWell;
|
||||
|
||||
cPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!cPtr->view) {
|
||||
free(cPtr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cPtr->colorView = W_CreateView(cPtr->view);
|
||||
if (!cPtr->colorView) {
|
||||
W_DestroyView(cPtr->view);
|
||||
free(cPtr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WMCreateEventHandler(cPtr->view, ExposureMask|StructureNotifyMask
|
||||
|ClientMessageMask, handleEvents, cPtr);
|
||||
|
||||
WMCreateEventHandler(cPtr->colorView, ExposureMask, handleEvents, cPtr);
|
||||
#if 0
|
||||
WMCreateEventHandler(cPtr->colorView, ButtonPressMask|Button1MotionMask,
|
||||
handleDragEvents, cPtr);
|
||||
#endif
|
||||
WMCreateEventHandler(cPtr->view, ButtonPressMask, handleActionEvents,
|
||||
cPtr);
|
||||
|
||||
cPtr->colorView->flags.mapWhenRealized = 1;
|
||||
|
||||
resizeColorWell(cPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
||||
return cPtr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetColorWellColor(WMColorWell *cPtr, WMColor *color)
|
||||
{
|
||||
if (cPtr->color)
|
||||
WMReleaseColor(cPtr->color);
|
||||
|
||||
cPtr->color = WMRetainColor(color);
|
||||
|
||||
if (cPtr->colorView->flags.realized && cPtr->colorView->flags.mapped)
|
||||
paintColorWell(cPtr);
|
||||
}
|
||||
|
||||
|
||||
WMColor*
|
||||
WMGetColorWellColor(WMColorWell *cPtr)
|
||||
{
|
||||
return cPtr->color;
|
||||
}
|
||||
|
||||
#define MIN(a,b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
static void
|
||||
resizeColorWell(WMColorWell *cPtr, unsigned int width, unsigned int height)
|
||||
{
|
||||
int bw;
|
||||
|
||||
if (width < MIN_WIDTH)
|
||||
width = MIN_WIDTH;
|
||||
if (height < MIN_HEIGHT)
|
||||
height = MIN_HEIGHT;
|
||||
|
||||
bw = (int)((float)MIN(width, height)*0.24);
|
||||
|
||||
W_ResizeView(cPtr->view, width, height);
|
||||
|
||||
W_ResizeView(cPtr->colorView, width-2*bw, height-2*bw);
|
||||
|
||||
if (cPtr->colorView->pos.x!=bw || cPtr->colorView->pos.y!=bw)
|
||||
W_MoveView(cPtr->colorView, bw, bw);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintColorWell(ColorWell *cPtr)
|
||||
{
|
||||
W_Screen *scr = cPtr->view->screen;
|
||||
|
||||
W_DrawRelief(scr, cPtr->view->window, 0, 0, cPtr->view->size.width,
|
||||
cPtr->view->size.height, WRRaised);
|
||||
|
||||
W_DrawRelief(scr, cPtr->colorView->window, 0, 0,
|
||||
cPtr->colorView->size.width, cPtr->colorView->size.height,
|
||||
WRSunken);
|
||||
|
||||
if (cPtr->color)
|
||||
WMPaintColorSwatch(cPtr->color, cPtr->colorView->window,
|
||||
2, 2, cPtr->colorView->size.width-4,
|
||||
cPtr->colorView->size.height-4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
ColorWell *cPtr = (ColorWell*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_ColorWell);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintColorWell(cPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyColorWell(cPtr);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static WMPixmap*
|
||||
makeDragPixmap(WMColorWell *cPtr)
|
||||
{
|
||||
WMScreen *scr = cPtr->view->screen;
|
||||
Pixmap pix;
|
||||
|
||||
pix = XCreatePixmap(scr->display, W_DRAWABLE(scr), 16, 16, scr->depth);
|
||||
|
||||
XFillRectangle(scr->display, pix, WMColorGC(cPtr->color), 0, 0, 15, 15);
|
||||
|
||||
XDrawRectangle(scr->display, pix, WMColorGC(scr->black), 0, 0, 15, 15);
|
||||
|
||||
return WMCreatePixmapFromXPixmaps(scr, pix, None, 16, 16, scr->depth);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleDragEvents(XEvent *event, void *data)
|
||||
{
|
||||
WMColorWell *cPtr = (ColorWell*)data;
|
||||
|
||||
switch (event->type) {
|
||||
case ButtonPress:
|
||||
if (event->xbutton.button == Button1) {
|
||||
cPtr->ipoint.x = event->xbutton.x;
|
||||
cPtr->ipoint.y = event->xbutton.y;
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
if (event->xmotion.state & Button1Mask) {
|
||||
if (abs(cPtr->ipoint.x - event->xmotion.x) > 4
|
||||
|| abs(cPtr->ipoint.y - event->xmotion.y) > 4) {
|
||||
WMSize offs;
|
||||
WMPixmap *pixmap;
|
||||
|
||||
offs.width = 2;
|
||||
offs.height = 2;
|
||||
pixmap = makeDragPixmap(cPtr);
|
||||
|
||||
WMDragImageFromView(cPtr->view, pixmap, cPtr->view->pos,
|
||||
offs, event, True);
|
||||
|
||||
WMReleasePixmap(pixmap);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
handleActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
/* WMColorWell *cPtr = (ColorWell*)data;*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
destroyColorWell(ColorWell *cPtr)
|
||||
{
|
||||
if (cPtr->color)
|
||||
WMReleaseColor(cPtr->color);
|
||||
|
||||
free(cPtr);
|
||||
}
|
||||
|
||||
918
WINGs/wevent.c
Normal file
918
WINGs/wevent.c
Normal file
@@ -0,0 +1,918 @@
|
||||
|
||||
|
||||
/*
|
||||
* This event handling stuff was based on Tk.
|
||||
*/
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include "../src/config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
# include <sys/time.h>
|
||||
# ifdef TIME_WITH_SYS_TIME
|
||||
# include <time.h>
|
||||
# endif
|
||||
#else /* ! HAVE_GETTIMEOFDAY */
|
||||
# include <time.h>
|
||||
#endif /* ! HAVE_GETTIMEOFDAY */
|
||||
|
||||
|
||||
extern _WINGsConfiguration WINGsConfiguration;
|
||||
|
||||
|
||||
|
||||
typedef struct TimerHandler {
|
||||
WMCallback *callback; /* procedure to call */
|
||||
unsigned long msec; /* when to call the callback */
|
||||
void *clientData;
|
||||
struct TimerHandler *next;
|
||||
} TimerHandler;
|
||||
|
||||
|
||||
typedef struct IdleHandler {
|
||||
WMCallback *callback;
|
||||
void *clientData;
|
||||
struct IdleHandler *next;
|
||||
} IdleHandler;
|
||||
|
||||
|
||||
typedef struct InputHandler {
|
||||
WMInputProc *callback;
|
||||
void *clientData;
|
||||
int fd;
|
||||
int mask;
|
||||
struct InputHandler *next;
|
||||
} InputHandler;
|
||||
|
||||
|
||||
/* table to map event types to event masks */
|
||||
static unsigned long eventMasks[] = {
|
||||
0,
|
||||
0,
|
||||
KeyPressMask, /* KeyPress */
|
||||
KeyReleaseMask, /* KeyRelease */
|
||||
ButtonPressMask, /* ButtonPress */
|
||||
ButtonReleaseMask, /* ButtonRelease */
|
||||
PointerMotionMask|PointerMotionHintMask|ButtonMotionMask
|
||||
|Button1MotionMask|Button2MotionMask|Button3MotionMask
|
||||
|Button4MotionMask|Button5MotionMask,
|
||||
/* MotionNotify */
|
||||
EnterWindowMask, /* EnterNotify */
|
||||
LeaveWindowMask, /* LeaveNotify */
|
||||
FocusChangeMask, /* FocusIn */
|
||||
FocusChangeMask, /* FocusOut */
|
||||
KeymapStateMask, /* KeymapNotify */
|
||||
ExposureMask, /* Expose */
|
||||
ExposureMask, /* GraphicsExpose */
|
||||
ExposureMask, /* NoExpose */
|
||||
VisibilityChangeMask, /* VisibilityNotify */
|
||||
SubstructureNotifyMask, /* CreateNotify */
|
||||
StructureNotifyMask, /* DestroyNotify */
|
||||
StructureNotifyMask, /* UnmapNotify */
|
||||
StructureNotifyMask, /* MapNotify */
|
||||
SubstructureRedirectMask, /* MapRequest */
|
||||
StructureNotifyMask, /* ReparentNotify */
|
||||
StructureNotifyMask, /* ConfigureNotify */
|
||||
SubstructureRedirectMask, /* ConfigureRequest */
|
||||
StructureNotifyMask, /* GravityNotify */
|
||||
ResizeRedirectMask, /* ResizeRequest */
|
||||
StructureNotifyMask, /* CirculateNotify */
|
||||
SubstructureRedirectMask, /* CirculateRequest */
|
||||
PropertyChangeMask, /* PropertyNotify */
|
||||
0, /* SelectionClear */
|
||||
0, /* SelectionRequest */
|
||||
0, /* SelectionNotify */
|
||||
ColormapChangeMask, /* ColormapNotify */
|
||||
ClientMessageMask, /* ClientMessage */
|
||||
0, /* Mapping Notify */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* queue of timer event handlers */
|
||||
static TimerHandler *timerHandler=NULL;
|
||||
|
||||
static IdleHandler *idleHandler=NULL;
|
||||
|
||||
static InputHandler *inputHandler=NULL;
|
||||
|
||||
/* hook for other toolkits or wmaker process their events */
|
||||
static WMEventHook *extraEventHandler=NULL;
|
||||
|
||||
|
||||
|
||||
#define timerPending() (timerHandler)
|
||||
|
||||
#define idlePending() (idleHandler)
|
||||
|
||||
|
||||
|
||||
/* return current time in milliseconds */
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
static unsigned long
|
||||
rightNow(void) {
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
return 1000L*(unsigned long)tv.tv_sec + (unsigned long)tv.tv_usec/1000L;
|
||||
}
|
||||
#else /* !HAVE_GETTIMEOFDAY */
|
||||
# define rightNow() (1000*(unsigned long)time(NULL))
|
||||
#endif /* !HAVE_GETTIMEOFDAY */
|
||||
|
||||
|
||||
WMHandlerID
|
||||
WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
|
||||
{
|
||||
TimerHandler *handler, *tmp;
|
||||
|
||||
handler = malloc(sizeof(TimerHandler));
|
||||
if (!handler)
|
||||
return NULL;
|
||||
|
||||
handler->msec = rightNow()+milliseconds;
|
||||
handler->callback = callback;
|
||||
handler->clientData = cdata;
|
||||
/* insert callback in queue, sorted by time left */
|
||||
if (!timerHandler || timerHandler->msec >= handler->msec) {
|
||||
/* first in the queue */
|
||||
handler->next = timerHandler;
|
||||
timerHandler = handler;
|
||||
} else {
|
||||
tmp = timerHandler;
|
||||
while (tmp->next && tmp->next->msec < handler->msec) {
|
||||
tmp = tmp->next;
|
||||
}
|
||||
handler->next = tmp->next;
|
||||
tmp->next = handler;
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMDeleteTimerWithClientData(void *cdata)
|
||||
{
|
||||
TimerHandler *handler, *tmp;
|
||||
|
||||
if (!cdata || !timerHandler)
|
||||
return;
|
||||
|
||||
tmp = timerHandler;
|
||||
if (tmp->clientData==cdata) {
|
||||
timerHandler = tmp->next;
|
||||
free(tmp);
|
||||
} else {
|
||||
while (tmp->next) {
|
||||
if (tmp->next->clientData==cdata) {
|
||||
handler = tmp->next;
|
||||
tmp->next = handler->next;
|
||||
free(handler);
|
||||
break;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMDeleteTimerHandler(WMHandlerID handlerID)
|
||||
{
|
||||
TimerHandler *tmp, *handler=(TimerHandler*)handlerID;
|
||||
|
||||
if (!handler || !timerHandler)
|
||||
return;
|
||||
|
||||
tmp = timerHandler;
|
||||
if (tmp==handler) {
|
||||
timerHandler = handler->next;
|
||||
free(handler);
|
||||
} else {
|
||||
while (tmp->next) {
|
||||
if (tmp->next==handler) {
|
||||
tmp->next=handler->next;
|
||||
free(handler);
|
||||
break;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMHandlerID
|
||||
WMAddIdleHandler(WMCallback *callback, void *cdata)
|
||||
{
|
||||
IdleHandler *handler, *tmp;
|
||||
|
||||
handler = malloc(sizeof(IdleHandler));
|
||||
if (!handler)
|
||||
return NULL;
|
||||
|
||||
handler->callback = callback;
|
||||
handler->clientData = cdata;
|
||||
handler->next = NULL;
|
||||
/* add callback at end of queue */
|
||||
if (!idleHandler) {
|
||||
idleHandler = handler;
|
||||
} else {
|
||||
tmp = idleHandler;
|
||||
while (tmp->next) {
|
||||
tmp = tmp->next;
|
||||
}
|
||||
tmp->next = handler;
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMDeleteIdleHandler(WMHandlerID handlerID)
|
||||
{
|
||||
IdleHandler *tmp, *handler = (IdleHandler*)handlerID;
|
||||
|
||||
if (!handler || !idleHandler)
|
||||
return;
|
||||
|
||||
tmp = idleHandler;
|
||||
if (tmp == handler) {
|
||||
idleHandler = handler->next;
|
||||
free(handler);
|
||||
} else {
|
||||
while (tmp->next) {
|
||||
if (tmp->next == handler) {
|
||||
tmp->next = handler->next;
|
||||
free(handler);
|
||||
break;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMHandlerID
|
||||
WMAddInputHandler(int fd, int condition, WMInputProc *proc, void *clientData)
|
||||
{
|
||||
InputHandler *handler;
|
||||
|
||||
handler = wmalloc(sizeof(InputHandler));
|
||||
|
||||
handler->fd = fd;
|
||||
handler->mask = condition;
|
||||
handler->callback = proc;
|
||||
handler->clientData = clientData;
|
||||
|
||||
handler->next = inputHandler;
|
||||
|
||||
inputHandler = handler;
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMDeleteInputHandler(WMHandlerID handlerID)
|
||||
{
|
||||
InputHandler *tmp, *handler = (InputHandler*)handlerID;
|
||||
|
||||
if (!handler || !inputHandler)
|
||||
return;
|
||||
|
||||
tmp = inputHandler;
|
||||
if (tmp == handler) {
|
||||
inputHandler = handler->next;
|
||||
free(handler);
|
||||
} else {
|
||||
while (tmp->next) {
|
||||
if (tmp->next == handler) {
|
||||
tmp->next = handler->next;
|
||||
free(handler);
|
||||
break;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
checkIdleHandlers()
|
||||
{
|
||||
IdleHandler *handler, *tmp;
|
||||
|
||||
if (!idleHandler)
|
||||
return;
|
||||
|
||||
handler = idleHandler;
|
||||
|
||||
/* we will process all idleHandlers so, empty the handler list */
|
||||
idleHandler = NULL;
|
||||
|
||||
while (handler) {
|
||||
tmp = handler->next;
|
||||
(*handler->callback)(handler->clientData);
|
||||
/* remove the handler */
|
||||
free(handler);
|
||||
|
||||
handler = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
checkTimerHandlers()
|
||||
{
|
||||
TimerHandler *handler;
|
||||
unsigned long now = rightNow();
|
||||
|
||||
if (!timerHandler || (timerHandler->msec > now))
|
||||
return;
|
||||
|
||||
while (timerHandler && timerHandler->msec <= now) {
|
||||
handler = timerHandler;
|
||||
timerHandler = timerHandler->next;
|
||||
handler->next = NULL;
|
||||
(*handler->callback)(handler->clientData);
|
||||
free(handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned long
|
||||
msToNextTimerEvent()
|
||||
{
|
||||
unsigned long now;
|
||||
|
||||
if (!timerHandler) {
|
||||
/* The return value of this function is only valid if there _are_
|
||||
timers active. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
now = rightNow();
|
||||
if (timerHandler->msec < now) {
|
||||
return 0;
|
||||
} else {
|
||||
return timerHandler->msec - now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* WMCreateEventHandler--
|
||||
* Create an event handler and put it in the event handler list for the
|
||||
* view. If the same callback and clientdata are already used in another
|
||||
* handler, the masks are swapped.
|
||||
*
|
||||
*/
|
||||
void
|
||||
WMCreateEventHandler(WMView *view, unsigned long mask, WMEventProc *eventProc,
|
||||
void *clientData)
|
||||
{
|
||||
W_EventHandler *handler;
|
||||
W_EventHandler *ptr = view->handlerList;
|
||||
unsigned long eventMask;
|
||||
|
||||
if (ptr==NULL) {
|
||||
handler = wmalloc(sizeof(W_EventHandler));
|
||||
|
||||
handler->nextHandler = NULL;
|
||||
|
||||
view->handlerList = handler;
|
||||
|
||||
eventMask = mask;
|
||||
} else {
|
||||
handler = NULL;
|
||||
eventMask = mask;
|
||||
while (ptr != NULL) {
|
||||
if (ptr->clientData == clientData && ptr->proc == eventProc) {
|
||||
handler = ptr;
|
||||
}
|
||||
eventMask |= ptr->eventMask;
|
||||
|
||||
ptr = ptr->nextHandler;
|
||||
}
|
||||
if (!handler) {
|
||||
handler = wmalloc(sizeof(W_EventHandler));
|
||||
handler->nextHandler = view->handlerList;
|
||||
view->handlerList = handler;
|
||||
}
|
||||
}
|
||||
|
||||
/* select events for window */
|
||||
handler->eventMask = mask;
|
||||
handler->proc = eventProc;
|
||||
handler->clientData = clientData;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* WMDeleteEventHandler--
|
||||
* Delete event handler matching arguments from windows
|
||||
* event handler list.
|
||||
*
|
||||
*/
|
||||
void
|
||||
WMDeleteEventHandler(WMView *view, unsigned long mask, WMEventProc *eventProc,
|
||||
void *clientData)
|
||||
{
|
||||
W_EventHandler *handler, *ptr, *pptr;
|
||||
|
||||
ptr = view->handlerList;
|
||||
|
||||
handler = NULL;
|
||||
pptr = NULL;
|
||||
|
||||
while (ptr!=NULL) {
|
||||
if (ptr->eventMask == mask && ptr->proc == eventProc
|
||||
&& ptr->clientData == clientData) {
|
||||
handler = ptr;
|
||||
break;
|
||||
}
|
||||
pptr = ptr;
|
||||
ptr = ptr->nextHandler;
|
||||
}
|
||||
|
||||
if (!handler)
|
||||
return;
|
||||
|
||||
if (!pptr) {
|
||||
view->handlerList = handler->nextHandler;
|
||||
} else {
|
||||
pptr->nextHandler = handler->nextHandler;
|
||||
}
|
||||
free(handler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
W_CleanUpEvents(WMView *view)
|
||||
{
|
||||
W_EventHandler *ptr, *nptr;
|
||||
|
||||
ptr = view->handlerList;
|
||||
|
||||
while (ptr!=NULL) {
|
||||
nptr = ptr->nextHandler;
|
||||
free(ptr);
|
||||
ptr = nptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Time
|
||||
getEventTime(WMScreen *screen, XEvent *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
return event->xbutton.time;
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
return event->xkey.time;
|
||||
case MotionNotify:
|
||||
return event->xmotion.time;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
return event->xcrossing.time;
|
||||
case PropertyNotify:
|
||||
return event->xproperty.time;
|
||||
case SelectionClear:
|
||||
return event->xselectionclear.time;
|
||||
case SelectionRequest:
|
||||
return event->xselectionrequest.time;
|
||||
case SelectionNotify:
|
||||
return event->xselection.time;
|
||||
default:
|
||||
return screen->lastEventTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_CallDestroyHandlers(W_View *view)
|
||||
{
|
||||
XEvent event;
|
||||
W_EventHandler *hPtr;
|
||||
|
||||
event.type = DestroyNotify;
|
||||
event.xdestroywindow.window = view->window;
|
||||
event.xdestroywindow.event = view->window;
|
||||
hPtr = view->handlerList;
|
||||
while (hPtr!=NULL) {
|
||||
if (hPtr->eventMask & StructureNotifyMask) {
|
||||
(*hPtr->proc)(&event, hPtr->clientData);
|
||||
}
|
||||
|
||||
hPtr = hPtr->nextHandler;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMHandleEvent(XEvent *event)
|
||||
{
|
||||
W_EventHandler *hPtr;
|
||||
W_View *view, *vPtr, *toplevel;
|
||||
unsigned long mask;
|
||||
Window window;
|
||||
|
||||
if (event->type == MappingNotify) {
|
||||
XRefreshKeyboardMapping(&event->xmapping);
|
||||
return True;
|
||||
}
|
||||
|
||||
mask = eventMasks[event->xany.type];
|
||||
|
||||
window = event->xany.window;
|
||||
|
||||
/* diferentiate SubstructureNotify with StructureNotify */
|
||||
if (mask == StructureNotifyMask) {
|
||||
if (event->xmap.event != event->xmap.window) {
|
||||
mask = SubstructureNotifyMask;
|
||||
window = event->xmap.event;
|
||||
}
|
||||
}
|
||||
view = W_GetViewForXWindow(event->xany.display, window);
|
||||
if (!view) {
|
||||
if (extraEventHandler)
|
||||
(extraEventHandler)(event);
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
view->screen->lastEventTime = getEventTime(view->screen, event);
|
||||
|
||||
toplevel = W_TopLevelOfView(view);
|
||||
|
||||
/* if it's a key event, redispatch it to the focused control */
|
||||
if (mask & (KeyPressMask|KeyReleaseMask)) {
|
||||
W_View *focused = W_FocusedViewOfToplevel(toplevel);
|
||||
|
||||
if (focused) {
|
||||
view = focused;
|
||||
}
|
||||
}
|
||||
|
||||
/* compress Motion events */
|
||||
if (event->type == MotionNotify && !view->flags.dontCompressMotion) {
|
||||
while (XPending(event->xmotion.display)) {
|
||||
XEvent ev;
|
||||
XPeekEvent(event->xmotion.display, &ev);
|
||||
if (ev.type == MotionNotify
|
||||
&& event->xmotion.window == ev.xmotion.window
|
||||
&& event->xmotion.subwindow == ev.xmotion.subwindow) {
|
||||
/* replace events */
|
||||
XNextEvent(event->xmotion.display, event);
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
|
||||
/* compress expose events */
|
||||
if (event->type == Expose && !view->flags.dontCompressExpose) {
|
||||
while (XCheckTypedWindowEvent(event->xexpose.display, view->window,
|
||||
Expose, event));
|
||||
}
|
||||
|
||||
|
||||
if (view->screen->modal && toplevel!=view->screen->modalView
|
||||
&& !toplevel->flags.worksWhenModal) {
|
||||
if (event->type == KeyPress || event->type == KeyRelease
|
||||
|| event->type == MotionNotify || event->type == ButtonPress
|
||||
|| event->type == ButtonRelease
|
||||
|| event->type == FocusIn || event->type == FocusOut) {
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a hack. It will make the panel be secure while
|
||||
* the event handlers are handled, as some event handler
|
||||
* might destroy the widget. */
|
||||
W_RetainView(toplevel);
|
||||
|
||||
hPtr = view->handlerList;
|
||||
|
||||
while (hPtr!=NULL) {
|
||||
W_EventHandler *tmp;
|
||||
|
||||
tmp = hPtr->nextHandler;
|
||||
|
||||
if ((hPtr->eventMask & mask)) {
|
||||
(*hPtr->proc)(event, hPtr->clientData);
|
||||
}
|
||||
|
||||
hPtr = tmp;
|
||||
}
|
||||
|
||||
/* pass the event to the top level window of the widget */
|
||||
if (view->parent!=NULL) {
|
||||
vPtr = view;
|
||||
while (vPtr->parent!=NULL)
|
||||
vPtr = vPtr->parent;
|
||||
|
||||
hPtr = vPtr->handlerList;
|
||||
|
||||
while (hPtr!=NULL) {
|
||||
|
||||
if (hPtr->eventMask & mask) {
|
||||
(*hPtr->proc)(event, hPtr->clientData);
|
||||
}
|
||||
hPtr = hPtr->nextHandler;
|
||||
}
|
||||
}
|
||||
|
||||
/* save button click info to track double-clicks */
|
||||
if (view->screen->ignoreNextDoubleClick) {
|
||||
view->screen->ignoreNextDoubleClick = 0;
|
||||
} else {
|
||||
if (event->type == ButtonPress) {
|
||||
view->screen->lastClickWindow = event->xbutton.window;
|
||||
view->screen->lastClickTime = event->xbutton.time;
|
||||
}
|
||||
}
|
||||
|
||||
W_ReleaseView(toplevel);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMIsDoubleClick(XEvent *event)
|
||||
{
|
||||
W_View *view;
|
||||
|
||||
if (event->type != ButtonPress)
|
||||
return False;
|
||||
|
||||
view = W_GetViewForXWindow(event->xany.display, event->xbutton.window);
|
||||
|
||||
if (!view)
|
||||
return False;
|
||||
|
||||
if (view->screen->lastClickWindow != event->xbutton.window)
|
||||
return False;
|
||||
|
||||
if (event->xbutton.time - view->screen->lastClickTime
|
||||
< WINGsConfiguration.doubleClickDelay) {
|
||||
view->screen->lastClickTime = 0;
|
||||
view->screen->lastClickWindow = None;
|
||||
view->screen->ignoreNextDoubleClick = 1;
|
||||
return True;
|
||||
} else
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
Bool
|
||||
W_WaitForEvent(Display *dpy, unsigned long xeventmask)
|
||||
{
|
||||
#ifndef HAVE_SELECT
|
||||
#error This_system_does_not_have_select(2)_and_is_not_supported
|
||||
#endif
|
||||
unsigned long milliseconds;
|
||||
struct timeval timeout;
|
||||
struct timeval *timeoutPtr;
|
||||
fd_set rset, wset, eset;
|
||||
int maxfd;
|
||||
int count;
|
||||
InputHandler *handler = inputHandler;
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_ZERO(&wset);
|
||||
FD_ZERO(&eset);
|
||||
|
||||
FD_SET(ConnectionNumber(dpy), &rset);
|
||||
maxfd = ConnectionNumber(dpy);
|
||||
|
||||
while (handler) {
|
||||
if (handler->mask & WIReadMask)
|
||||
FD_SET(handler->fd, &rset);
|
||||
|
||||
if (handler->mask & WIWriteMask)
|
||||
FD_SET(handler->fd, &wset);
|
||||
|
||||
if (handler->mask & WIExceptMask)
|
||||
FD_SET(handler->fd, &eset);
|
||||
|
||||
if (maxfd < handler->fd)
|
||||
maxfd = handler->fd;
|
||||
|
||||
handler = handler->next;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Setup the select() timeout to the estimated time until the
|
||||
* next timer expires.
|
||||
*/
|
||||
if (timerPending()) {
|
||||
milliseconds = msToNextTimerEvent();
|
||||
timeout.tv_sec = milliseconds / 1000;
|
||||
timeout.tv_usec = (milliseconds % 1000) * 1000;
|
||||
timeoutPtr = &timeout;
|
||||
} else {
|
||||
timeoutPtr = (struct timeval*)0;
|
||||
}
|
||||
|
||||
XSync(dpy, False);
|
||||
if (xeventmask==0) {
|
||||
if (XPending(dpy))
|
||||
return True;
|
||||
} else {
|
||||
XEvent ev;
|
||||
if (XCheckMaskEvent(dpy, xeventmask, &ev)) {
|
||||
XPutBackEvent(dpy, &ev);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
/* TODO: port to poll() */
|
||||
count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr);
|
||||
|
||||
if (count > 0) {
|
||||
handler = inputHandler;
|
||||
|
||||
while (handler) {
|
||||
int mask;
|
||||
|
||||
mask = 0;
|
||||
|
||||
if (FD_ISSET(handler->fd, &rset))
|
||||
mask |= WIReadMask;
|
||||
|
||||
if (FD_ISSET(handler->fd, &wset))
|
||||
mask |= WIWriteMask;
|
||||
|
||||
if (FD_ISSET(handler->fd, &eset))
|
||||
mask |= WIExceptMask;
|
||||
|
||||
if (mask!=0 && handler->callback) {
|
||||
(*handler->callback)(handler->fd, mask,
|
||||
handler->clientData);
|
||||
}
|
||||
|
||||
handler = handler->next;
|
||||
}
|
||||
}
|
||||
|
||||
return FD_ISSET(ConnectionNumber(dpy), &rset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMNextEvent(Display *dpy, XEvent *event)
|
||||
{
|
||||
/* Check any expired timers */
|
||||
if (timerPending()) {
|
||||
checkTimerHandlers();
|
||||
}
|
||||
|
||||
while (XPending(dpy) == 0) {
|
||||
/* Do idle stuff */
|
||||
/* Do idle and timer stuff while there are no timer or X events */
|
||||
while (!XPending(dpy) && idlePending()) {
|
||||
if (idlePending())
|
||||
checkIdleHandlers();
|
||||
/* dispatch timer events */
|
||||
if (timerPending())
|
||||
checkTimerHandlers();
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that new events did not arrive while we were doing
|
||||
* timer/idle stuff. Or we might block forever waiting for
|
||||
* an event that already arrived.
|
||||
*/
|
||||
/* wait to something happen */
|
||||
W_WaitForEvent(dpy, 0);
|
||||
|
||||
/* Check any expired timers */
|
||||
if (timerPending()) {
|
||||
checkTimerHandlers();
|
||||
}
|
||||
}
|
||||
|
||||
XNextEvent(dpy, event);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
WMMaskEvent(Display *dpy, long mask, XEvent *event)
|
||||
{
|
||||
unsigned long milliseconds;
|
||||
struct timeval timeout;
|
||||
struct timeval *timeoutOrInfty;
|
||||
fd_set readset;
|
||||
|
||||
while (!XCheckMaskEvent(dpy, mask, event)) {
|
||||
/* Do idle stuff while there are no timer or X events */
|
||||
while (idlePending()) {
|
||||
checkIdleHandlers();
|
||||
if (XCheckMaskEvent(dpy, mask, event))
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the select() timeout to the estimated time until the
|
||||
* next timer expires.
|
||||
*/
|
||||
if (timerPending()) {
|
||||
milliseconds = msToNextTimerEvent();
|
||||
timeout.tv_sec = milliseconds / 1000;
|
||||
timeout.tv_usec = (milliseconds % 1000) * 1000;
|
||||
timeoutOrInfty = &timeout;
|
||||
} else {
|
||||
timeoutOrInfty = (struct timeval*)0;
|
||||
}
|
||||
|
||||
if (XCheckMaskEvent(dpy, mask, event))
|
||||
return;
|
||||
|
||||
/* Wait for input on the X connection socket */
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(ConnectionNumber(dpy), &readset);
|
||||
select(1 + ConnectionNumber(dpy), &readset, (fd_set*)0, (fd_set*)0,
|
||||
timeoutOrInfty);
|
||||
|
||||
/* Check any expired timers */
|
||||
if (timerPending()) {
|
||||
checkTimerHandlers();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
/*
|
||||
* Cant use this because XPending() will make W_WaitForEvent
|
||||
* return even if the event in the queue is not what we want,
|
||||
* and if we block until some new event arrives from the
|
||||
* server, other events already in the queue (like Expose)
|
||||
* will be deferred.
|
||||
*/
|
||||
void
|
||||
WMMaskEvent(Display *dpy, long mask, XEvent *event)
|
||||
{
|
||||
while (!XCheckMaskEvent(dpy, mask, event)) {
|
||||
/* Do idle stuff while there are no timer or X events */
|
||||
while (idlePending()) {
|
||||
checkIdleHandlers();
|
||||
if (XCheckMaskEvent(dpy, mask, event))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wait for input on the X connection socket */
|
||||
W_WaitForEvent(dpy, mask);
|
||||
|
||||
/* Check any expired timers */
|
||||
if (timerPending()) {
|
||||
checkTimerHandlers();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Bool
|
||||
WMScreenPending(WMScreen *scr)
|
||||
{
|
||||
if (XPending(scr->display))
|
||||
return True;
|
||||
else
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
WMEventHook*
|
||||
WMHookEventHandler(WMEventHook *handler)
|
||||
{
|
||||
WMEventHook *oldHandler = extraEventHandler;
|
||||
|
||||
extraEventHandler = handler;
|
||||
|
||||
return oldHandler;
|
||||
}
|
||||
|
||||
|
||||
559
WINGs/wfilepanel.c
Normal file
559
WINGs/wfilepanel.c
Normal file
@@ -0,0 +1,559 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
typedef struct W_FilePanel {
|
||||
WMWindow *win;
|
||||
|
||||
WMLabel *iconLabel;
|
||||
WMLabel *titleLabel;
|
||||
|
||||
WMFrame *line;
|
||||
|
||||
WMLabel *nameLabel;
|
||||
WMBrowser *browser;
|
||||
|
||||
WMButton *okButton;
|
||||
WMButton *cancelButton;
|
||||
|
||||
WMButton *homeButton;
|
||||
|
||||
WMTextField *fileField;
|
||||
|
||||
char **fileTypes;
|
||||
|
||||
struct {
|
||||
unsigned int canExit:1;
|
||||
unsigned int canceled:1; /* clicked on cancel */
|
||||
unsigned int done:1;
|
||||
unsigned int filtered:1;
|
||||
unsigned int canChooseFiles:1;
|
||||
unsigned int canChooseDirectories:1;
|
||||
unsigned int showAllFiles:1;
|
||||
unsigned int canFreeFileTypes:1;
|
||||
unsigned int fileMustExist:1;
|
||||
} flags;
|
||||
} W_FilePanel;
|
||||
|
||||
|
||||
#define PWIDTH 320
|
||||
#define PHEIGHT 360
|
||||
|
||||
static void listDirectoryOnColumn(WMFilePanel *panel, int column, char *path);
|
||||
static void browserClick();
|
||||
|
||||
static void fillColumn(WMBrowser *bPtr, int column);
|
||||
|
||||
static void goHome();
|
||||
|
||||
static void buttonClick();
|
||||
|
||||
static char *getCurrentFileName(WMFilePanel *panel);
|
||||
|
||||
static int
|
||||
closestListItem(WMList *list, char *text)
|
||||
{
|
||||
WMListItem *item = WMGetListItem(list, 0);
|
||||
int i = 0;
|
||||
int len = strlen(text);
|
||||
|
||||
if (len==0)
|
||||
return -1;
|
||||
|
||||
while (item) {
|
||||
if (strlen(item->text) >= len && strncmp(item->text, text, len)==0) {
|
||||
return i;
|
||||
}
|
||||
item = item->nextPtr;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
textChangedObserver(void *observerData, WMNotification *notification)
|
||||
{
|
||||
W_FilePanel *panel = (W_FilePanel*)observerData;
|
||||
char *text;
|
||||
WMList *list;
|
||||
int col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
|
||||
int i;
|
||||
|
||||
list = WMGetBrowserListInColumn(panel->browser, col);
|
||||
if (!list)
|
||||
return;
|
||||
text = WMGetTextFieldText(panel->fileField);
|
||||
|
||||
i = closestListItem(list, text);
|
||||
WMSelectListItem(list, i);
|
||||
if (i>=0)
|
||||
WMSetListPosition(list, i);
|
||||
|
||||
free(text);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
textEditedObserver(void *observerData, WMNotification *notification)
|
||||
{
|
||||
W_FilePanel *panel = (W_FilePanel*)observerData;
|
||||
|
||||
if ((int)WMGetNotificationClientData(notification)==WMReturnTextMovement) {
|
||||
WMPerformButtonClick(panel->okButton);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static WMFilePanel*
|
||||
makeFilePanel(WMScreen *scrPtr, char *name, char *title)
|
||||
{
|
||||
WMFilePanel *fPtr;
|
||||
WMFont *largeFont;
|
||||
|
||||
fPtr = wmalloc(sizeof(WMFilePanel));
|
||||
memset(fPtr, 0, sizeof(WMFilePanel));
|
||||
|
||||
fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask
|
||||
|WMResizableWindowMask);
|
||||
WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
|
||||
WMSetWindowTitle(fPtr->win, "");
|
||||
|
||||
fPtr->iconLabel = WMCreateLabel(fPtr->win);
|
||||
WMResizeWidget(fPtr->iconLabel, 64, 64);
|
||||
WMMoveWidget(fPtr->iconLabel, 0, 0);
|
||||
WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
|
||||
WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIcon);
|
||||
|
||||
fPtr->titleLabel = WMCreateLabel(fPtr->win);
|
||||
WMResizeWidget(fPtr->titleLabel, PWIDTH-64, 64);
|
||||
WMMoveWidget(fPtr->titleLabel, 64, 0);
|
||||
largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
|
||||
WMSetLabelFont(fPtr->titleLabel, largeFont);
|
||||
WMReleaseFont(largeFont);
|
||||
WMSetLabelText(fPtr->titleLabel, title);
|
||||
|
||||
fPtr->line = WMCreateFrame(fPtr->win);
|
||||
WMMoveWidget(fPtr->line, 0, 64);
|
||||
WMResizeWidget(fPtr->line, PWIDTH, 2);
|
||||
WMSetFrameRelief(fPtr->line, WRGroove);
|
||||
|
||||
fPtr->browser = WMCreateBrowser(fPtr->win);
|
||||
WMSetBrowserFillColumnProc(fPtr->browser, fillColumn);
|
||||
WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
|
||||
WMMoveWidget(fPtr->browser, 7, 72);
|
||||
WMHangData(fPtr->browser, fPtr);
|
||||
|
||||
fPtr->nameLabel = WMCreateLabel(fPtr->win);
|
||||
WMMoveWidget(fPtr->nameLabel, 7, 282);
|
||||
WMResizeWidget(fPtr->nameLabel, 55, 14);
|
||||
WMSetLabelText(fPtr->nameLabel, "Name:");
|
||||
|
||||
fPtr->fileField = WMCreateTextField(fPtr->win);
|
||||
WMMoveWidget(fPtr->fileField, 60, 278);
|
||||
WMResizeWidget(fPtr->fileField, PWIDTH-60-10, 24);
|
||||
WMAddNotificationObserver(textEditedObserver, fPtr,
|
||||
WMTextDidEndEditingNotification,
|
||||
fPtr->fileField);
|
||||
WMAddNotificationObserver(textChangedObserver, fPtr,
|
||||
WMTextDidChangeNotification,
|
||||
fPtr->fileField);
|
||||
|
||||
fPtr->okButton = WMCreateCommandButton(fPtr->win);
|
||||
WMMoveWidget(fPtr->okButton, 230, 325);
|
||||
WMResizeWidget(fPtr->okButton, 80, 28);
|
||||
WMSetButtonText(fPtr->okButton, "OK");
|
||||
WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
|
||||
WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
|
||||
WMSetButtonImagePosition(fPtr->okButton, WIPRight);
|
||||
WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
|
||||
|
||||
fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
|
||||
WMMoveWidget(fPtr->cancelButton, 140, 325);
|
||||
WMResizeWidget(fPtr->cancelButton, 80, 28);
|
||||
WMSetButtonText(fPtr->cancelButton, "Cancel");
|
||||
WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
|
||||
|
||||
fPtr->homeButton = WMCreateCommandButton(fPtr->win);
|
||||
WMMoveWidget(fPtr->homeButton, 55, 325);
|
||||
WMResizeWidget(fPtr->homeButton, 28, 28);
|
||||
WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
|
||||
WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
|
||||
WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
|
||||
|
||||
WMRealizeWidget(fPtr->win);
|
||||
WMMapSubwidgets(fPtr->win);
|
||||
|
||||
WMLoadBrowserColumnZero(fPtr->browser);
|
||||
|
||||
fPtr->flags.canChooseFiles = 1;
|
||||
fPtr->flags.canChooseDirectories = 1;
|
||||
|
||||
return fPtr;
|
||||
}
|
||||
|
||||
|
||||
WMOpenPanel*
|
||||
WMGetOpenPanel(WMScreen *scrPtr)
|
||||
{
|
||||
WMFilePanel *panel;
|
||||
|
||||
if (scrPtr->sharedOpenPanel)
|
||||
return scrPtr->sharedOpenPanel;
|
||||
|
||||
panel = makeFilePanel(scrPtr, "openFilePanel", "Open");
|
||||
panel->flags.fileMustExist = 1;
|
||||
|
||||
scrPtr->sharedOpenPanel = panel;
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
WMSavePanel*
|
||||
WMGetSavePanel(WMScreen *scrPtr)
|
||||
{
|
||||
WMFilePanel *panel;
|
||||
|
||||
if (scrPtr->sharedSavePanel)
|
||||
return scrPtr->sharedSavePanel;
|
||||
|
||||
panel = makeFilePanel(scrPtr, "saveFilePanel", "Save");
|
||||
panel->flags.fileMustExist = 0;
|
||||
|
||||
scrPtr->sharedSavePanel = panel;
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMFreeFilePanel(WMFilePanel *panel)
|
||||
{
|
||||
if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
|
||||
WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
|
||||
}
|
||||
WMRemoveNotificationObserver(panel);
|
||||
WMUnmapWidget(panel->win);
|
||||
WMDestroyWidget(panel->win);
|
||||
free(panel);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMRunModalSavePanelForDirectory(WMFilePanel *panel, WMWindow *owner,
|
||||
char *path, char *name)
|
||||
{
|
||||
WMScreen *scr = WMWidgetScreen(panel->win);
|
||||
XEvent event;
|
||||
|
||||
WMChangePanelOwner(panel->win, owner);
|
||||
|
||||
WMSetFilePanelDirectory(panel, path);
|
||||
|
||||
panel->flags.done = 0;
|
||||
panel->fileTypes = NULL;
|
||||
|
||||
panel->flags.filtered = 0;
|
||||
|
||||
WMMapWidget(panel->win);
|
||||
|
||||
while (!panel->flags.done) {
|
||||
WMNextEvent(scr->display, &event);
|
||||
WMHandleEvent(&event);
|
||||
}
|
||||
|
||||
WMCloseWindow(panel->win);
|
||||
|
||||
return (panel->flags.canceled ? False : True);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
WMRunModalOpenPanelForDirectory(WMFilePanel *panel, WMWindow *owner,
|
||||
char *path, char *name, char **fileTypes)
|
||||
{
|
||||
WMScreen *scr = WMWidgetScreen(panel->win);
|
||||
XEvent event;
|
||||
|
||||
WMChangePanelOwner(panel->win, owner);
|
||||
|
||||
WMSetFilePanelDirectory(panel, path);
|
||||
|
||||
panel->flags.done = 0;
|
||||
|
||||
if (fileTypes)
|
||||
panel->flags.filtered = 1;
|
||||
panel->fileTypes = fileTypes;
|
||||
|
||||
WMMapWidget(panel->win);
|
||||
|
||||
while (!panel->flags.done) {
|
||||
WMNextEvent(scr->display, &event);
|
||||
WMHandleEvent(&event);
|
||||
}
|
||||
|
||||
WMCloseWindow(panel->win);
|
||||
|
||||
return (panel->flags.canceled ? False : True);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetFilePanelDirectory(WMFilePanel *panel, char *path)
|
||||
{
|
||||
WMList *list;
|
||||
WMListItem *item;
|
||||
int col;
|
||||
|
||||
WMSetBrowserPath(panel->browser, path);
|
||||
col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
|
||||
list = WMGetBrowserListInColumn(panel->browser, col);
|
||||
if (list && (item = WMGetListSelectedItem(list))) {
|
||||
if (item->isBranch) {
|
||||
WMSetTextFieldText(panel->fileField, NULL);
|
||||
} else {
|
||||
WMSetTextFieldText(panel->fileField, item->text);
|
||||
}
|
||||
} else {
|
||||
WMSetTextFieldText(panel->fileField, path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetFilePanelCanChooseDirectories(WMFilePanel *panel, int flag)
|
||||
{
|
||||
panel->flags.canChooseDirectories = flag;
|
||||
}
|
||||
|
||||
void
|
||||
WMSetFilePanelCanChooseFiles(WMFilePanel *panel, int flag)
|
||||
{
|
||||
panel->flags.canChooseFiles = flag;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMGetFilePanelFileName(WMFilePanel *panel)
|
||||
{
|
||||
return getCurrentFileName(panel);
|
||||
}
|
||||
|
||||
|
||||
static char*
|
||||
get_name_from_path(char *path)
|
||||
{
|
||||
int size;
|
||||
|
||||
assert(path!=NULL);
|
||||
|
||||
size = strlen(path);
|
||||
|
||||
/* remove trailing / */
|
||||
while (size > 0 && path[size-1]=='/')
|
||||
size--;
|
||||
/* directory was root */
|
||||
if (size == 0)
|
||||
return wstrdup("/");
|
||||
|
||||
while (size > 0 && path[size-1] != '/')
|
||||
size--;
|
||||
|
||||
return wstrdup(&(path[size]));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
filterFileName(WMFilePanel *panel, char *file, Bool isDirectory)
|
||||
{
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
listDirectoryOnColumn(WMFilePanel *panel, int column, char *path)
|
||||
{
|
||||
WMBrowser *bPtr = panel->browser;
|
||||
struct dirent *dentry;
|
||||
DIR *dir;
|
||||
struct stat stat_buf;
|
||||
char pbuf[PATH_MAX+16];
|
||||
|
||||
assert(column >= 0);
|
||||
assert(path != NULL);
|
||||
|
||||
/* put directory name in the title */
|
||||
WMSetBrowserColumnTitle(bPtr, column, get_name_from_path(path));
|
||||
|
||||
dir = opendir(path);
|
||||
|
||||
if (!dir) {
|
||||
#ifdef VERBOSE
|
||||
printf("WINGs: could not open directory %s\n", path);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* list contents in the column */
|
||||
while ((dentry = readdir(dir))) {
|
||||
if (strcmp(dentry->d_name, ".")==0 ||
|
||||
strcmp(dentry->d_name, "..")==0)
|
||||
continue;
|
||||
|
||||
strcpy(pbuf, path);
|
||||
if (strcmp(path, "/")!=0)
|
||||
strcat(pbuf, "/");
|
||||
strcat(pbuf, dentry->d_name);
|
||||
|
||||
if (stat(pbuf, &stat_buf)!=0) {
|
||||
#ifdef VERBOSE
|
||||
printf("WINGs: could not stat %s\n", pbuf);
|
||||
#endif
|
||||
continue;
|
||||
} else {
|
||||
int isDirectory;
|
||||
|
||||
isDirectory = S_ISDIR(stat_buf.st_mode);
|
||||
|
||||
if (filterFileName(panel, dentry->d_name, isDirectory))
|
||||
WMAddSortedBrowserItem(bPtr, column, dentry->d_name,
|
||||
isDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fillColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
char *path;
|
||||
WMFilePanel *panel;
|
||||
|
||||
if (column > 0) {
|
||||
path = WMGetBrowserPathToColumn(bPtr, column-1);
|
||||
} else {
|
||||
path = wstrdup("/");
|
||||
}
|
||||
|
||||
panel = WMGetHangedData(bPtr);
|
||||
listDirectoryOnColumn(panel, column, path);
|
||||
free(path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
browserClick(WMBrowser *bPtr, WMFilePanel *panel)
|
||||
{
|
||||
int col = WMGetBrowserSelectedColumn(bPtr);
|
||||
WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
|
||||
|
||||
if (!item || item->isBranch)
|
||||
WMSetTextFieldText(panel->fileField, NULL);
|
||||
else {
|
||||
WMSetTextFieldText(panel->fileField, item->text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
goHome(WMButton *bPtr, WMFilePanel *panel)
|
||||
{
|
||||
char *home;
|
||||
|
||||
/* home is statically allocated. Don't free it! */
|
||||
home = wgethomedir();
|
||||
if (!home)
|
||||
return;
|
||||
|
||||
WMSetFilePanelDirectory(panel, home);
|
||||
}
|
||||
|
||||
|
||||
static char*
|
||||
getCurrentFileName(WMFilePanel *panel)
|
||||
{
|
||||
char *path;
|
||||
char *file;
|
||||
char *tmp;
|
||||
int len;
|
||||
|
||||
path = WMGetBrowserPath(panel->browser);
|
||||
|
||||
len = strlen(path);
|
||||
if (path[len-1]=='/') {
|
||||
file = WMGetTextFieldText(panel->fileField);
|
||||
tmp = wmalloc(strlen(path)+strlen(file)+8);
|
||||
strcpy(tmp, path);
|
||||
strcat(tmp, file);
|
||||
free(file);
|
||||
free(path);
|
||||
return tmp;
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Bool
|
||||
validOpenFile(WMFilePanel *panel)
|
||||
{
|
||||
WMListItem *item;
|
||||
int col;
|
||||
|
||||
col = WMGetBrowserSelectedColumn(panel->browser);
|
||||
item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
|
||||
if (item) {
|
||||
if (item->isBranch && !panel->flags.canChooseDirectories)
|
||||
return False;
|
||||
else if (!item->isBranch && !panel->flags.canChooseFiles)
|
||||
return False;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
buttonClick(WMButton *bPtr, WMFilePanel *panel)
|
||||
{
|
||||
if (bPtr == panel->okButton) {
|
||||
if (panel->flags.fileMustExist) {
|
||||
char *file;
|
||||
if (!validOpenFile(panel))
|
||||
return;
|
||||
|
||||
file = getCurrentFileName(panel);
|
||||
if (access(file, F_OK)!=0) {
|
||||
WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
|
||||
"Error", "File does not exist.",
|
||||
"Ok", NULL, NULL);
|
||||
free(file);
|
||||
return;
|
||||
}
|
||||
free(file);
|
||||
}
|
||||
panel->flags.canceled = 0;
|
||||
} else
|
||||
panel->flags.canceled = 1;
|
||||
|
||||
panel->flags.done = 1;
|
||||
}
|
||||
272
WINGs/wfont.c
Normal file
272
WINGs/wfont.c
Normal file
@@ -0,0 +1,272 @@
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
#include <wraster.h>
|
||||
#include <assert.h>
|
||||
|
||||
static char *makeFontSetOfSize(char *fontset, int size);
|
||||
|
||||
|
||||
WMFont*
|
||||
WMCreateFont(WMScreen *scrPtr, char *fontName)
|
||||
{
|
||||
WMFont *font;
|
||||
Display *display = scrPtr->display;
|
||||
char **missing;
|
||||
int nmissing = 0;
|
||||
char *defaultString;
|
||||
XFontSetExtents *extents;
|
||||
|
||||
font = malloc(sizeof(WMFont));
|
||||
if (!font)
|
||||
return NULL;
|
||||
|
||||
font->notFontSet = 0;
|
||||
|
||||
font->screen = scrPtr;
|
||||
|
||||
font->font.set = XCreateFontSet(display, fontName, &missing, &nmissing,
|
||||
&defaultString);
|
||||
if (nmissing > 0 && font->font.set) {
|
||||
int i;
|
||||
|
||||
wwarning("the following character sets are missing in %s:",
|
||||
fontName);
|
||||
for (i = 0; i < nmissing; i++) {
|
||||
wwarning(missing[i]);
|
||||
}
|
||||
XFreeStringList(missing);
|
||||
if (defaultString)
|
||||
wwarning("the string \"%s\" will be used in place of any characters from those sets.",
|
||||
defaultString);
|
||||
}
|
||||
if (!font->font.set) {
|
||||
free(font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extents = XExtentsOfFontSet(font->font.set);
|
||||
|
||||
font->height = extents->max_logical_extent.height;
|
||||
font->y = font->height - (font->height + extents->max_logical_extent.y);
|
||||
|
||||
font->refCount = 1;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMFont*
|
||||
WMCreateFontInDefaultEncoding(WMScreen *scrPtr, char *fontName)
|
||||
{
|
||||
WMFont *font;
|
||||
Display *display = scrPtr->display;
|
||||
|
||||
font = malloc(sizeof(WMFont));
|
||||
if (!font)
|
||||
return NULL;
|
||||
|
||||
font->notFontSet = 1;
|
||||
|
||||
font->screen = scrPtr;
|
||||
|
||||
font->font.normal = XLoadQueryFont(display, fontName);
|
||||
if (!font->font.normal) {
|
||||
free(font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
font->height = font->font.normal->ascent+font->font.normal->descent;
|
||||
font->y = font->font.normal->ascent;
|
||||
|
||||
font->refCount = 1;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMFont*
|
||||
WMRetainFont(WMFont *font)
|
||||
{
|
||||
assert(font!=NULL);
|
||||
|
||||
font->refCount++;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMReleaseFont(WMFont *font)
|
||||
{
|
||||
assert(font!=NULL);
|
||||
font->refCount--;
|
||||
if (font->refCount < 1) {
|
||||
if (font->notFontSet)
|
||||
XFreeFont(font->screen->display, font->font.normal);
|
||||
else
|
||||
XFreeFontSet(font->screen->display, font->font.set);
|
||||
free(font);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int
|
||||
WMFontHeight(WMFont *font)
|
||||
{
|
||||
assert(font!=NULL);
|
||||
|
||||
return font->height;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
WMFont*
|
||||
WMSystemFontOfSize(WMScreen *scrPtr, int size)
|
||||
{
|
||||
WMFont *font;
|
||||
char *fontSpec;
|
||||
|
||||
fontSpec = makeFontSetOfSize(WINGsConfiguration.systemFont, size);
|
||||
|
||||
font = WMCreateFont(scrPtr, fontSpec);
|
||||
|
||||
if (!font) {
|
||||
wwarning("could not load font set %s. Trying fixed.", fontSpec);
|
||||
font = WMCreateFont(scrPtr, "fixed");
|
||||
if (!font) {
|
||||
wwarning("could not load fixed font!");
|
||||
free(fontSpec);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
free(fontSpec);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
WMFont*
|
||||
WMBoldSystemFontOfSize(WMScreen *scrPtr, int size)
|
||||
{
|
||||
WMFont *font;
|
||||
char *fontSpec;
|
||||
|
||||
fontSpec = makeFontSetOfSize(WINGsConfiguration.boldSystemFont, size);
|
||||
|
||||
font = WMCreateFont(scrPtr, fontSpec);
|
||||
|
||||
if (!font) {
|
||||
wwarning("could not load font set %s. Trying fixed.", fontSpec);
|
||||
font = WMCreateFont(scrPtr, "fixed");
|
||||
if (!font) {
|
||||
wwarning("could not load fixed font!");
|
||||
free(fontSpec);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
free(fontSpec);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
XFontSet
|
||||
WMGetFontFontSet(WMFont *font)
|
||||
{
|
||||
if (font->notFontSet)
|
||||
return NULL;
|
||||
else
|
||||
return font->font.set;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMWidthOfString(WMFont *font, char *text, int length)
|
||||
{
|
||||
assert(font!=NULL);
|
||||
assert(text!=NULL);
|
||||
|
||||
if (font->notFontSet)
|
||||
return XTextWidth(font->font.normal, text, length);
|
||||
else {
|
||||
XRectangle rect;
|
||||
XRectangle AIXsucks;
|
||||
|
||||
XmbTextExtents(font->font.set, text, length, &AIXsucks, &rect);
|
||||
|
||||
return rect.width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMDrawString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
|
||||
char *text, int length)
|
||||
{
|
||||
if (font->notFontSet) {
|
||||
XSetFont(scr->display, gc, font->font.normal->fid);
|
||||
XDrawString(scr->display, d, gc, x, y + font->y, text, length);
|
||||
} else {
|
||||
XmbDrawString(scr->display, d, font->font.set, gc, x, y + font->y,
|
||||
text, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMDrawImageString(WMScreen *scr, Drawable d, GC gc, WMFont *font, int x, int y,
|
||||
char *text, int length)
|
||||
{
|
||||
if (font->notFontSet) {
|
||||
XSetFont(scr->display, gc, font->font.normal->fid);
|
||||
XDrawImageString(scr->display, d, gc, x, y + font->y, text, length);
|
||||
} else {
|
||||
XmbDrawImageString(scr->display, d, font->font.set, gc, x, y + font->y,
|
||||
text, length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static char*
|
||||
makeFontSetOfSize(char *fontset, int size)
|
||||
{
|
||||
char font[300];
|
||||
char *newfs = NULL;
|
||||
char *ptr;
|
||||
char *tmp;
|
||||
|
||||
do {
|
||||
int hold = ' ';
|
||||
|
||||
ptr = strchr(fontset, ',');
|
||||
if (ptr) {
|
||||
hold = *(ptr+1);
|
||||
*(ptr+1) = 0;
|
||||
}
|
||||
if (strlen(fontset)>255) {
|
||||
wwarning("font description %s is too large.", fontset);
|
||||
} else {
|
||||
sprintf(font, fontset, size);
|
||||
tmp = wstrappend(newfs, font);
|
||||
if (newfs)
|
||||
free(newfs);
|
||||
newfs = tmp;
|
||||
}
|
||||
if (ptr) {
|
||||
*(ptr+1) = hold;
|
||||
}
|
||||
fontset = ptr+1;
|
||||
} while (ptr!=NULL);
|
||||
|
||||
return newfs;
|
||||
}
|
||||
|
||||
654
WINGs/wfontpanel.c
Normal file
654
WINGs/wfontpanel.c
Normal file
@@ -0,0 +1,654 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
|
||||
typedef struct W_FontPanel {
|
||||
WMWindow *win;
|
||||
|
||||
WMFrame *upperF;
|
||||
WMLabel *sampleL;
|
||||
|
||||
WMSplitView *split;
|
||||
|
||||
WMFrame *lowerF;
|
||||
WMLabel *famL;
|
||||
WMList *famLs;
|
||||
WMLabel *typL;
|
||||
WMList *typLs;
|
||||
WMLabel *sizL;
|
||||
WMTextField *sizT;
|
||||
WMList *sizLs;
|
||||
|
||||
WMFrame *xlfdF;
|
||||
WMTextField *xlfdT;
|
||||
|
||||
WMFrame *encF;
|
||||
WMPopUpButton *encP;
|
||||
|
||||
WMButton *revertB;
|
||||
WMButton *previewB;
|
||||
WMButton *setB;
|
||||
|
||||
proplist_t fdb;
|
||||
} FontPanel;
|
||||
|
||||
|
||||
#define MIN_UPPER_HEIGHT 20
|
||||
#define MIN_LOWER_HEIGHT 140
|
||||
|
||||
|
||||
#define MAX_FONTS_TO_RETRIEVE 2000
|
||||
|
||||
|
||||
#define MIN_WIDTH 250
|
||||
#define MIN_HEIGHT MIN_UPPER_HEIGHT+MIN_LOWER_HEIGHT+70
|
||||
|
||||
/*
|
||||
static char *scalableFontSizes[] = {
|
||||
"8",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"14",
|
||||
"16",
|
||||
"18",
|
||||
"20",
|
||||
"24",
|
||||
"36",
|
||||
"48",
|
||||
"64"
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
static void arrangeLowerFrame(FontPanel *panel);
|
||||
|
||||
static proplist_t createFontDatabase(WMScreen *scr);
|
||||
|
||||
static void listFamilies(proplist_t fdb, WMList *list);
|
||||
|
||||
static void
|
||||
splitViewConstrainCallback(WMSplitView *sPtr, int divIndex, int *min, int *max)
|
||||
{
|
||||
*min = MIN_UPPER_HEIGHT;
|
||||
*max = WMWidgetHeight(sPtr)-WMGetSplitViewDividerThickness(sPtr)-MIN_LOWER_HEIGHT;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
notificationObserver(void *self, WMNotification *notif)
|
||||
{
|
||||
WMFontPanel *panel = (WMFontPanel*)self;
|
||||
void *object = WMGetNotificationObject(notif);
|
||||
|
||||
if (WMGetNotificationName(notif) == WMViewSizeDidChangeNotification) {
|
||||
if (object == WMWidgetView(panel->win)) {
|
||||
int h = WMWidgetHeight(panel->win);
|
||||
int w = WMWidgetWidth(panel->win);
|
||||
|
||||
WMResizeWidget(panel->split, w, h-40);
|
||||
|
||||
WMMoveWidget(panel->setB, w-80, h-35);
|
||||
WMMoveWidget(panel->previewB, w-160, h-35);
|
||||
WMMoveWidget(panel->revertB, w-240, h-35);
|
||||
} else if (object == WMWidgetView(panel->upperF)) {
|
||||
WMResizeWidget(panel->sampleL, WMWidgetWidth(panel->upperF)-20,
|
||||
WMWidgetHeight(panel->upperF)-10);
|
||||
} else if (object == WMWidgetView(panel->lowerF)) {
|
||||
|
||||
if (WMWidgetHeight(panel->lowerF) < MIN_LOWER_HEIGHT) {
|
||||
int h;
|
||||
|
||||
h = WMWidgetHeight(panel->split)-MIN_LOWER_HEIGHT
|
||||
- WMGetSplitViewDividerThickness(panel->split);
|
||||
|
||||
WMResizeWidget(panel->upperF, WMWidgetWidth(panel->upperF), h);
|
||||
|
||||
WMMoveWidget(panel->lowerF, 0, WMWidgetHeight(panel->upperF)
|
||||
+ WMGetSplitViewDividerThickness(panel->split));
|
||||
WMResizeWidget(panel->lowerF, WMWidgetWidth(panel->lowerF),
|
||||
MIN_LOWER_HEIGHT);
|
||||
} else {
|
||||
arrangeLowerFrame(panel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static void
|
||||
familyClick(WMWidget *w, void *data)
|
||||
{
|
||||
WMList *lPtr = (WMList*)w;
|
||||
FontPanel *panel = (FontPanel*)data;
|
||||
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
WMFontPanel*
|
||||
WMGetFontPanel(WMScreen *scr)
|
||||
{
|
||||
FontPanel *panel;
|
||||
WMColor *dark, *white;
|
||||
WMFont *font;
|
||||
int divThickness;
|
||||
|
||||
if (scr->sharedFontPanel)
|
||||
return scr->sharedFontPanel;
|
||||
|
||||
|
||||
panel = wmalloc(sizeof(FontPanel));
|
||||
memset(panel, 0, sizeof(FontPanel));
|
||||
|
||||
panel->win = WMCreateWindow(scr, "fontPanel");
|
||||
WMResizeWidget(panel->win, 320, 370);
|
||||
WMSetWindowMinSize(panel->win, MIN_WIDTH, MIN_HEIGHT);
|
||||
WMSetViewNotifySizeChanges(WMWidgetView(panel->win), True);
|
||||
|
||||
panel->split = WMCreateSplitView(panel->win);
|
||||
WMResizeWidget(panel->split, 320, 330);
|
||||
WMSetSplitViewConstrainProc(panel->split, splitViewConstrainCallback);
|
||||
|
||||
divThickness = WMGetSplitViewDividerThickness(panel->split);
|
||||
|
||||
panel->upperF = WMCreateFrame(panel->win);
|
||||
WMSetFrameRelief(panel->upperF, WRFlat);
|
||||
WMSetViewNotifySizeChanges(WMWidgetView(panel->upperF), True);
|
||||
panel->lowerF = WMCreateFrame(panel->win);
|
||||
WMSetFrameRelief(panel->lowerF, WRFlat);
|
||||
WMSetViewNotifySizeChanges(WMWidgetView(panel->lowerF), True);
|
||||
|
||||
WMAddSplitViewSubview(panel->split, W_VIEW(panel->upperF));
|
||||
WMAddSplitViewSubview(panel->split, W_VIEW(panel->lowerF));
|
||||
|
||||
WMResizeWidget(panel->upperF, 320, 60);
|
||||
WMResizeWidget(panel->lowerF, 320, 330-60-divThickness);
|
||||
WMMoveWidget(panel->lowerF, 0, 60+divThickness);
|
||||
|
||||
white = WMWhiteColor(scr);
|
||||
dark = WMDarkGrayColor(scr);
|
||||
|
||||
panel->sampleL = WMCreateLabel(panel->upperF);
|
||||
WMResizeWidget(panel->sampleL, 300, 50);
|
||||
WMMoveWidget(panel->sampleL, 10, 10);
|
||||
WMSetWidgetBackgroundColor(panel->sampleL, white);
|
||||
WMSetLabelRelief(panel->sampleL, WRSunken);
|
||||
WMSetLabelText(panel->sampleL, "It is not yet completed!!!");
|
||||
|
||||
font = WMBoldSystemFontOfSize(scr, 12);
|
||||
|
||||
panel->famL = WMCreateLabel(panel->lowerF);
|
||||
WMSetWidgetBackgroundColor(panel->famL, dark);
|
||||
WMSetLabelText(panel->famL, "Family");
|
||||
WMSetLabelFont(panel->famL, font);
|
||||
WMSetLabelTextColor(panel->famL, white);
|
||||
WMSetLabelRelief(panel->famL, WRSunken);
|
||||
WMSetLabelTextAlignment(panel->famL, WACenter);
|
||||
|
||||
panel->famLs = WMCreateList(panel->lowerF);
|
||||
|
||||
panel->typL = WMCreateLabel(panel->lowerF);
|
||||
WMSetWidgetBackgroundColor(panel->typL, dark);
|
||||
WMSetLabelText(panel->typL, "Typeface");
|
||||
WMSetLabelFont(panel->typL, font);
|
||||
WMSetLabelTextColor(panel->typL, white);
|
||||
WMSetLabelRelief(panel->typL, WRSunken);
|
||||
WMSetLabelTextAlignment(panel->typL, WACenter);
|
||||
|
||||
panel->typLs = WMCreateList(panel->lowerF);
|
||||
|
||||
panel->sizL = WMCreateLabel(panel->lowerF);
|
||||
WMSetWidgetBackgroundColor(panel->sizL, dark);
|
||||
WMSetLabelText(panel->sizL, "Size");
|
||||
WMSetLabelFont(panel->sizL, font);
|
||||
WMSetLabelTextColor(panel->sizL, white);
|
||||
WMSetLabelRelief(panel->sizL, WRSunken);
|
||||
WMSetLabelTextAlignment(panel->sizL, WACenter);
|
||||
|
||||
panel->sizT = WMCreateTextField(panel->lowerF);
|
||||
|
||||
panel->sizLs = WMCreateList(panel->lowerF);
|
||||
|
||||
WMReleaseFont(font);
|
||||
WMReleaseColor(white);
|
||||
WMReleaseColor(dark);
|
||||
|
||||
panel->encF = WMCreateFrame(panel->lowerF);
|
||||
WMSetFrameTitle(panel->encF, "Encoding");
|
||||
WMResizeWidget(panel->encF, 130, 50);
|
||||
|
||||
panel->encP = WMCreatePopUpButton(panel->encF);
|
||||
WMMoveWidget(panel->encP, 10, 20);
|
||||
WMResizeWidget(panel->encP, 112, 20);
|
||||
|
||||
WMMapSubwidgets(panel->encF);
|
||||
|
||||
panel->xlfdF = WMCreateFrame(panel->lowerF);
|
||||
WMSetFrameTitle(panel->xlfdF, "Xtra Long Font Description");
|
||||
|
||||
panel->xlfdT = WMCreateTextField(panel->xlfdF);
|
||||
WMMoveWidget(panel->xlfdT, 10, 20);
|
||||
|
||||
WMMapSubwidgets(panel->xlfdF);
|
||||
|
||||
arrangeLowerFrame(panel);
|
||||
|
||||
panel->setB = WMCreateCommandButton(panel->win);
|
||||
WMResizeWidget(panel->setB, 70, 24);
|
||||
WMMoveWidget(panel->setB, 240, 335);
|
||||
WMSetButtonText(panel->setB, "Set");
|
||||
|
||||
panel->previewB = WMCreateCommandButton(panel->win);
|
||||
WMResizeWidget(panel->previewB, 70, 24);
|
||||
WMMoveWidget(panel->previewB, 160, 335);
|
||||
WMSetButtonText(panel->previewB, "Preview");
|
||||
|
||||
panel->revertB = WMCreateCommandButton(panel->win);
|
||||
WMResizeWidget(panel->revertB, 70, 24);
|
||||
WMMoveWidget(panel->revertB, 80, 335);
|
||||
WMSetButtonText(panel->revertB, "Revert");
|
||||
|
||||
WMRealizeWidget(panel->win);
|
||||
|
||||
WMMapSubwidgets(panel->upperF);
|
||||
WMMapSubwidgets(panel->lowerF);
|
||||
WMMapSubwidgets(panel->split);
|
||||
WMMapSubwidgets(panel->win);
|
||||
|
||||
scr->sharedFontPanel = panel;
|
||||
|
||||
|
||||
/* register notification observers */
|
||||
WMAddNotificationObserver(notificationObserver, panel,
|
||||
WMViewSizeDidChangeNotification,
|
||||
WMWidgetView(panel->win));
|
||||
WMAddNotificationObserver(notificationObserver, panel,
|
||||
WMViewSizeDidChangeNotification,
|
||||
WMWidgetView(panel->upperF));
|
||||
WMAddNotificationObserver(notificationObserver, panel,
|
||||
WMViewSizeDidChangeNotification,
|
||||
WMWidgetView(panel->lowerF));
|
||||
|
||||
panel->fdb = createFontDatabase(scr);
|
||||
listFamilies(panel->fdb, panel->famLs);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMFreeFontPanel(WMFontPanel *panel)
|
||||
{
|
||||
if (panel == WMWidgetScreen(panel->win)->sharedFontPanel) {
|
||||
WMWidgetScreen(panel->win)->sharedFontPanel = NULL;
|
||||
}
|
||||
WMRemoveNotificationObserver(panel);
|
||||
WMUnmapWidget(panel->win);
|
||||
WMDestroyWidget(panel->win);
|
||||
free(panel);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMShowFontPanel(WMFontPanel *panel)
|
||||
{
|
||||
WMMapWidget(panel->win);
|
||||
}
|
||||
|
||||
void
|
||||
WMHideFontPanel(WMFontPanel *panel)
|
||||
{
|
||||
WMUnmapWidget(panel->win);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetFontPanelFont(WMFontPanel *panel, WMFont *font)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
WMFont*
|
||||
WMGetFontPanelFont(WMFontPanel *panel)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMGetFontPanelFontName(WMFontPanel *panel)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
arrangeLowerFrame(FontPanel *panel)
|
||||
{
|
||||
int width = WMWidgetWidth(panel->lowerF) - 55 - 30;
|
||||
int height = WMWidgetHeight(panel->lowerF);
|
||||
int oheight = 330-60-WMGetSplitViewDividerThickness(panel->split);
|
||||
int fw, tw, sw;
|
||||
int h;
|
||||
|
||||
height -= 20 + 3 + 10 + 50;
|
||||
oheight -= 20 + 3 + 10 + 50;
|
||||
|
||||
fw = (125*width) / 235;
|
||||
tw = (110*width) / 235;
|
||||
sw = 55;
|
||||
|
||||
h = (174*height) / oheight;
|
||||
|
||||
WMMoveWidget(panel->famL, 10, 0);
|
||||
WMResizeWidget(panel->famL, fw, 20);
|
||||
|
||||
WMMoveWidget(panel->famLs, 10, 23);
|
||||
WMResizeWidget(panel->famLs, fw, h);
|
||||
|
||||
WMMoveWidget(panel->typL, 10+fw+3, 0);
|
||||
WMResizeWidget(panel->typL, tw, 20);
|
||||
|
||||
WMMoveWidget(panel->typLs, 10+fw+3, 23);
|
||||
WMResizeWidget(panel->typLs, tw, h);
|
||||
|
||||
WMMoveWidget(panel->sizL, 10+fw+3+tw+3, 0);
|
||||
WMResizeWidget(panel->sizL, sw+4, 20);
|
||||
|
||||
WMMoveWidget(panel->sizT, 10+fw+3+tw+3, 23);
|
||||
WMResizeWidget(panel->sizT, sw+4, 20);
|
||||
|
||||
WMMoveWidget(panel->sizLs, 10+fw+3+tw+3, 46);
|
||||
WMResizeWidget(panel->sizLs, sw+4, h-22);
|
||||
|
||||
WMMoveWidget(panel->encF, 10, WMWidgetHeight(panel->lowerF)-55);
|
||||
|
||||
WMMoveWidget(panel->xlfdF, 145, WMWidgetHeight(panel->lowerF)-55);
|
||||
WMResizeWidget(panel->xlfdF, WMWidgetWidth(panel->lowerF)-155, 50);
|
||||
|
||||
WMResizeWidget(panel->xlfdT, WMWidgetWidth(panel->lowerF)-155-20, 20);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define ALL_FONTS_MASK "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
|
||||
|
||||
#define FOUNDRY 0
|
||||
#define FAMILY 1
|
||||
#define WEIGHT 2
|
||||
#define SLANT 3
|
||||
#define SETWIDTH 4
|
||||
#define ADD_STYLE 5
|
||||
#define PIXEL_SIZE 6
|
||||
#define POINT_SIZE 7
|
||||
#define RES_X 8
|
||||
#define RES_Y 9
|
||||
#define SPACING 10
|
||||
#define AV_WIDTH 11
|
||||
#define REGISTRY 12
|
||||
#define ENCODING 13
|
||||
|
||||
#define NUM_FIELDS 14
|
||||
|
||||
|
||||
static Bool
|
||||
parseFont(char *font, char **values)
|
||||
{
|
||||
char *ptr;
|
||||
int part;
|
||||
char buffer[256], *bptr;
|
||||
|
||||
part = FOUNDRY;
|
||||
ptr = font;
|
||||
ptr++; /* skip first - */
|
||||
bptr = buffer;
|
||||
while (*ptr) {
|
||||
if (*ptr == '-') {
|
||||
*bptr = 0;
|
||||
values[part]=wstrdup(buffer);
|
||||
bptr = buffer;
|
||||
part++;
|
||||
} else {
|
||||
*bptr++ = *ptr;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
*bptr = 0;
|
||||
values[part]=wstrdup(buffer);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
isXLFD(char *font, int *length_ret)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
*length_ret = 0;
|
||||
while (*font) {
|
||||
(*length_ret)++;
|
||||
if (*font++ == '-')
|
||||
c++;
|
||||
}
|
||||
|
||||
return c==NUM_FIELDS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static proplist_t foundryKey = NULL;
|
||||
static proplist_t typeKey = NULL;
|
||||
static proplist_t sizeKey, encKey, xlfdKey;
|
||||
|
||||
|
||||
static void
|
||||
addSizeToEnc(proplist_t enc, char **fields)
|
||||
{
|
||||
proplist_t sizel;
|
||||
|
||||
sizel = PLGetDictionaryEntry(enc, sizeKey);
|
||||
if (!sizel) {
|
||||
sizel = PLMakeArrayFromElements(PLMakeString(fields[PIXEL_SIZE]),NULL);
|
||||
PLInsertDictionaryEntry(enc, sizeKey, sizel);
|
||||
} else {
|
||||
PLAppendArrayElement(sizel, PLMakeString(fields[PIXEL_SIZE]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static proplist_t
|
||||
addTypefaceToFont(proplist_t font, char **fields)
|
||||
{
|
||||
proplist_t face, encod, facedic, encodic;
|
||||
char buffer[256];
|
||||
|
||||
strcpy(buffer, fields[WEIGHT]);
|
||||
|
||||
if (strcasecmp(fields[SLANT], "R")==0)
|
||||
strcat(buffer, " Roman ");
|
||||
else if (strcasecmp(fields[SLANT], "I")==0)
|
||||
strcat(buffer, " Italic ");
|
||||
else if (strcasecmp(fields[SLANT], "O")==0)
|
||||
strcat(buffer, " Oblique ");
|
||||
else if (strcasecmp(fields[SLANT], "RI")==0)
|
||||
strcat(buffer, " Reverse Italic ");
|
||||
else if (strcasecmp(fields[SLANT], "RO")==0)
|
||||
strcat(buffer, " Reverse Oblique ");
|
||||
else if (strcasecmp(fields[SLANT], "OT")==0)
|
||||
strcat(buffer, " ? ");
|
||||
/* else
|
||||
* polymorphic fonts
|
||||
*/
|
||||
strcat(buffer, fields[SETWIDTH]);
|
||||
strcat(buffer, " ");
|
||||
strcat(buffer, fields[ADD_STYLE]);
|
||||
|
||||
face = PLMakeString(buffer);
|
||||
|
||||
facedic = PLGetDictionaryEntry(font, face);
|
||||
if (!facedic) {
|
||||
facedic = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
|
||||
PLInsertDictionaryEntry(font, face, facedic);
|
||||
PLRelease(facedic);
|
||||
}
|
||||
PLRelease(face);
|
||||
|
||||
strcpy(buffer, fields[REGISTRY]);
|
||||
strcat(buffer, "-");
|
||||
strcat(buffer, fields[ENCODING]);
|
||||
encod = PLMakeString(buffer);
|
||||
|
||||
encodic = PLGetDictionaryEntry(facedic, encod);
|
||||
if (!encodic) {
|
||||
proplist_t tmp;
|
||||
sprintf(buffer, "-%s-%s-%s-%s-%s-%s-%%d-0-%s-%s-%s-%s-%s-%s",
|
||||
fields[FOUNDRY], fields[FAMILY], fields[WEIGHT],
|
||||
fields[SLANT], fields[SETWIDTH], fields[ADD_STYLE],
|
||||
fields[RES_X], fields[RES_Y], fields[SPACING],
|
||||
fields[AV_WIDTH], fields[REGISTRY], fields[ENCODING]);
|
||||
tmp = PLMakeString(buffer);
|
||||
|
||||
encodic = PLMakeDictionaryFromEntries(xlfdKey, tmp, NULL);
|
||||
PLRelease(tmp);
|
||||
PLInsertDictionaryEntry(facedic, encod, encodic);
|
||||
PLRelease(encodic);
|
||||
}
|
||||
addSizeToEnc(encodic, fields);
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
static proplist_t
|
||||
makeFontEntry(char **fields)
|
||||
{
|
||||
proplist_t font;
|
||||
proplist_t value;
|
||||
proplist_t tmp;
|
||||
value = PLMakeString(fields[FOUNDRY]);
|
||||
|
||||
tmp = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
|
||||
|
||||
font = PLMakeDictionaryFromEntries(foundryKey, value,
|
||||
typeKey, tmp,
|
||||
NULL);
|
||||
PLRelease(value);
|
||||
PLRelease(tmp);
|
||||
|
||||
addTypefaceToFont(font, fields);
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
static proplist_t
|
||||
createFontDatabase(WMScreen *scr)
|
||||
{
|
||||
char **fontList;
|
||||
int count;
|
||||
char *fields[NUM_FIELDS];
|
||||
int font_name_length;
|
||||
char buffer[256];
|
||||
int i;
|
||||
proplist_t fdb;
|
||||
proplist_t font;
|
||||
proplist_t family;
|
||||
proplist_t foundry;
|
||||
proplist_t tmp;
|
||||
|
||||
if (!foundryKey) {
|
||||
foundryKey = PLMakeString("Foundry");
|
||||
typeKey = PLMakeString("Typeface");
|
||||
encKey = PLMakeString("Encoding");
|
||||
sizeKey = PLMakeString("Sizes");
|
||||
xlfdKey = PLMakeString("XLFD");
|
||||
}
|
||||
|
||||
/* retrieve a complete listing of the available fonts */
|
||||
fontList = XListFonts(scr->display, ALL_FONTS_MASK, MAX_FONTS_TO_RETRIEVE,
|
||||
&count);
|
||||
if (!fontList) {
|
||||
wwarning("could not retrieve font list");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fdb = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
if (!isXLFD(fontList[i], &font_name_length)) {
|
||||
continue;
|
||||
}
|
||||
/* the XLFD specs limit the size of a font description in 255 chars */
|
||||
assert(font_name_length < 256);
|
||||
|
||||
if (parseFont(fontList[i], fields)) {
|
||||
family = PLMakeString(fields[FAMILY]);
|
||||
font = PLGetDictionaryEntry(fdb, family);
|
||||
if (font) {
|
||||
foundry = PLGetDictionaryEntry(font, foundryKey);
|
||||
if (strcmp(PLGetString(foundry), fields[FOUNDRY])==0) {
|
||||
/* already a font with the same family */
|
||||
addTypefaceToFont(font, fields);
|
||||
} else {
|
||||
/* same font family by different foundries */
|
||||
sprintf(buffer, "%s (%s)", fields[FAMILY],
|
||||
fields[FOUNDRY]);
|
||||
PLRelease(family);
|
||||
family = PLMakeString(buffer);
|
||||
|
||||
font = PLGetDictionaryEntry(fdb, family);
|
||||
if (font) {
|
||||
/* already a font with the same family */
|
||||
addTypefaceToFont(font, fields);
|
||||
} else {
|
||||
tmp = makeFontEntry(fields);
|
||||
PLInsertDictionaryEntry(fdb, family, tmp);
|
||||
PLRelease(tmp);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tmp = makeFontEntry(fields);
|
||||
PLInsertDictionaryEntry(fdb, family, tmp);
|
||||
PLRelease(tmp);
|
||||
}
|
||||
PLRelease(family);
|
||||
}
|
||||
}
|
||||
XFreeFontNames(fontList);
|
||||
|
||||
return fdb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
listFamilies(proplist_t fdb, WMList *list)
|
||||
{
|
||||
proplist_t arr;
|
||||
proplist_t fam;
|
||||
int i;
|
||||
|
||||
arr = PLGetAllDictionaryKeys(fdb);
|
||||
for (i = 0; i<PLGetNumberOfElements(arr); i++) {
|
||||
fam = PLGetArrayElement(arr, i);
|
||||
WMAddSortedListItem(list, PLGetString(fam));
|
||||
}
|
||||
}
|
||||
223
WINGs/wframe.c
Normal file
223
WINGs/wframe.c
Normal file
@@ -0,0 +1,223 @@
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
typedef struct W_Frame {
|
||||
W_Class widgetClass;
|
||||
W_View *view;
|
||||
|
||||
char *caption;
|
||||
|
||||
|
||||
struct {
|
||||
WMReliefType relief:3;
|
||||
WMTitlePosition titlePosition:3;
|
||||
} flags;
|
||||
} Frame;
|
||||
|
||||
|
||||
|
||||
struct W_ViewProcedureTable _FrameViewProcedures = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#define DEFAULT_RELIEF WRGroove
|
||||
#define DEFAULT_TITLE_POSITION WTPAtTop
|
||||
#define DEFAULT_WIDTH 40
|
||||
#define DEFAULT_HEIGHT 40
|
||||
|
||||
|
||||
static void destroyFrame(Frame *fPtr);
|
||||
static void paintFrame(Frame *fPtr);
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetFrameTitlePosition(WMFrame *fPtr, WMTitlePosition position)
|
||||
{
|
||||
fPtr->flags.titlePosition = position;
|
||||
|
||||
if (fPtr->view->flags.realized) {
|
||||
paintFrame(fPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetFrameRelief(WMFrame *fPtr, WMReliefType relief)
|
||||
{
|
||||
fPtr->flags.relief = relief;
|
||||
|
||||
if (fPtr->view->flags.realized) {
|
||||
paintFrame(fPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetFrameTitle(WMFrame *fPtr, char *title)
|
||||
{
|
||||
if (fPtr->caption)
|
||||
free(fPtr->caption);
|
||||
if (title)
|
||||
fPtr->caption = wstrdup(title);
|
||||
else
|
||||
fPtr->caption = NULL;
|
||||
|
||||
if (fPtr->view->flags.realized) {
|
||||
paintFrame(fPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintFrame(Frame *fPtr)
|
||||
{
|
||||
W_View *view = fPtr->view;
|
||||
W_Screen *scrPtr = view->screen;
|
||||
int tx, ty, tw, th;
|
||||
int fy, fh;
|
||||
|
||||
if (fPtr->caption!=NULL)
|
||||
th = scrPtr->normalFont->height;
|
||||
else {
|
||||
th = 0;
|
||||
}
|
||||
|
||||
fh = view->size.height;
|
||||
fy = 0;
|
||||
|
||||
switch (fPtr->flags.titlePosition) {
|
||||
case WTPAboveTop:
|
||||
ty = 0;
|
||||
fy = th + 4;
|
||||
fh = view->size.height - fy;
|
||||
break;
|
||||
|
||||
case WTPAtTop:
|
||||
ty = 0;
|
||||
fy = th/2;
|
||||
fh = view->size.height - fy;
|
||||
break;
|
||||
|
||||
case WTPBelowTop:
|
||||
ty = 4;
|
||||
fy = 0;
|
||||
fh = view->size.height;
|
||||
break;
|
||||
|
||||
case WTPAboveBottom:
|
||||
ty = view->size.height - th - 4;
|
||||
fy = 0;
|
||||
fh = view->size.height;
|
||||
break;
|
||||
|
||||
case WTPAtBottom:
|
||||
ty = view->size.height - th;
|
||||
fy = 0;
|
||||
fh = view->size.height - th/2;
|
||||
break;
|
||||
|
||||
case WTPBelowBottom:
|
||||
ty = view->size.height - th;
|
||||
fy = 0;
|
||||
fh = view->size.height - th - 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
ty = 0;
|
||||
fy = 0;
|
||||
fh = view->size.height;
|
||||
}
|
||||
/*
|
||||
XClearArea(scrPtr->display, view->window, fy+2, 2, fh-4, view->size.width-4,
|
||||
False);
|
||||
*/
|
||||
XClearWindow(scrPtr->display, view->window);
|
||||
|
||||
W_DrawRelief(scrPtr, view->window, 0, fy, view->size.width, fh,
|
||||
fPtr->flags.relief);
|
||||
|
||||
if (fPtr->caption!=NULL && fPtr->flags.titlePosition!=WTPNoTitle) {
|
||||
|
||||
|
||||
tw = WMWidthOfString(scrPtr->normalFont, fPtr->caption,
|
||||
strlen(fPtr->caption));
|
||||
|
||||
tx = (view->size.width - tw) / 2;
|
||||
|
||||
XFillRectangle(scrPtr->display, view->window, W_GC(scrPtr->gray),
|
||||
tx, ty, tw, th);
|
||||
|
||||
WMDrawString(scrPtr, view->window, W_GC(scrPtr->black),
|
||||
scrPtr->normalFont, tx, ty, fPtr->caption,
|
||||
strlen(fPtr->caption));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
Frame *fPtr = (Frame*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_Frame);
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintFrame(fPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyFrame(fPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMFrame*
|
||||
WMCreateFrame(WMWidget *parent)
|
||||
{
|
||||
Frame *fPtr;
|
||||
|
||||
fPtr = wmalloc(sizeof(Frame));
|
||||
memset(fPtr, 0, sizeof(Frame));
|
||||
|
||||
fPtr->widgetClass = WC_Frame;
|
||||
|
||||
fPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!fPtr->view) {
|
||||
free(fPtr);
|
||||
return NULL;
|
||||
}
|
||||
fPtr->view->self = fPtr;
|
||||
|
||||
WMCreateEventHandler(fPtr->view, ExposureMask|StructureNotifyMask,
|
||||
handleEvents, fPtr);
|
||||
|
||||
|
||||
fPtr->flags.relief = DEFAULT_RELIEF;
|
||||
fPtr->flags.titlePosition = DEFAULT_TITLE_POSITION;
|
||||
|
||||
WMResizeWidget(fPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
||||
return fPtr;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
destroyFrame(Frame *fPtr)
|
||||
{
|
||||
if (fPtr->caption)
|
||||
free(fPtr->caption);
|
||||
|
||||
free(fPtr);
|
||||
}
|
||||
894
WINGs/widgets.c
Normal file
894
WINGs/widgets.c
Normal file
@@ -0,0 +1,894 @@
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
/********** data ************/
|
||||
|
||||
|
||||
#define CHECK_BUTTON_ON_WIDTH 16
|
||||
#define CHECK_BUTTON_ON_HEIGHT 16
|
||||
|
||||
static char *CHECK_BUTTON_ON[] = {
|
||||
" %",
|
||||
" .............%#",
|
||||
" ........... .%#",
|
||||
" .......... #.%#",
|
||||
" ......... #%.%#",
|
||||
" ........ #%..%#",
|
||||
" ... #.. #%...%#",
|
||||
" ... #% #%....%#",
|
||||
" ... % #%.....%#",
|
||||
" ... #%......%#",
|
||||
" ... #%.......%#",
|
||||
" ...#%........%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" %%%%%%%%%%%%%%#",
|
||||
"%###############"};
|
||||
|
||||
#define CHECK_BUTTON_OFF_WIDTH 16
|
||||
#define CHECK_BUTTON_OFF_HEIGHT 16
|
||||
|
||||
static char *CHECK_BUTTON_OFF[] = {
|
||||
" %",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" .............%#",
|
||||
" %%%%%%%%%%%%%%#",
|
||||
"%###############"};
|
||||
|
||||
#define RADIO_BUTTON_ON_WIDTH 15
|
||||
#define RADIO_BUTTON_ON_HEIGHT 15
|
||||
static char *RADIO_BUTTON_ON[] = {
|
||||
".....%%%%%.....",
|
||||
"...%%#####%%...",
|
||||
"..%##.....%.%..",
|
||||
".%#%.. .....",
|
||||
".%#. ...",
|
||||
"%#.. .. ",
|
||||
"%#. . ",
|
||||
"%#. . ",
|
||||
"%#. . ",
|
||||
"%#. . ",
|
||||
".%%. . .",
|
||||
".%.. . .",
|
||||
"..%... .. ..",
|
||||
".... ..... ...",
|
||||
"..... .....",
|
||||
};
|
||||
|
||||
#define RADIO_BUTTON_OFF_WIDTH 15
|
||||
#define RADIO_BUTTON_OFF_HEIGHT 15
|
||||
static char *RADIO_BUTTON_OFF[] = {
|
||||
".....%%%%%.....",
|
||||
"...%%#####%%...",
|
||||
"..%##.......%..",
|
||||
".%#%...........",
|
||||
".%#............",
|
||||
"%#............ ",
|
||||
"%#............ ",
|
||||
"%#............ ",
|
||||
"%#............ ",
|
||||
"%#............ ",
|
||||
".%%.......... .",
|
||||
".%........... .",
|
||||
"..%......... ..",
|
||||
".... ..... ...",
|
||||
"..... .....",
|
||||
};
|
||||
|
||||
|
||||
static char *BUTTON_ARROW[] = {
|
||||
"..................",
|
||||
"....##....#### ...",
|
||||
"...#.%....#... ...",
|
||||
"..#..%#####... ...",
|
||||
".#............ ...",
|
||||
"#............. ...",
|
||||
".#............ ...",
|
||||
"..#.. ...",
|
||||
"...#. ............",
|
||||
"....# ............"
|
||||
};
|
||||
|
||||
#define BUTTON_ARROW_WIDTH 18
|
||||
#define BUTTON_ARROW_HEIGHT 10
|
||||
|
||||
|
||||
static char *BUTTON_ARROW2[] = {
|
||||
" ",
|
||||
" ## ####. ",
|
||||
" # % # . ",
|
||||
" # %##### . ",
|
||||
" # . ",
|
||||
"# . ",
|
||||
" # . ",
|
||||
" # .......... ",
|
||||
" # . ",
|
||||
" #. "
|
||||
};
|
||||
|
||||
#define BUTTON_ARROW2_WIDTH 18
|
||||
#define BUTTON_ARROW2_HEIGHT 10
|
||||
|
||||
|
||||
static char *SCROLLER_DIMPLE[] = {
|
||||
".%###.",
|
||||
"%#%%%%",
|
||||
"#%%...",
|
||||
"#%.. ",
|
||||
"#%. ",
|
||||
".%. ."
|
||||
};
|
||||
|
||||
#define SCROLLER_DIMPLE_WIDTH 6
|
||||
#define SCROLLER_DIMPLE_HEIGHT 6
|
||||
|
||||
|
||||
static char *SCROLLER_ARROW_UP[] = {
|
||||
"....%....",
|
||||
"....#....",
|
||||
"...%#%...",
|
||||
"...###...",
|
||||
"..%###%..",
|
||||
"..#####..",
|
||||
".%#####%.",
|
||||
".#######.",
|
||||
"%#######%"
|
||||
};
|
||||
|
||||
static char *HI_SCROLLER_ARROW_UP[] = {
|
||||
" % ",
|
||||
" % ",
|
||||
" %%% ",
|
||||
" %%% ",
|
||||
" %%%%% ",
|
||||
" %%%%% ",
|
||||
" %%%%%%% ",
|
||||
" %%%%%%% ",
|
||||
"%%%%%%%%%"
|
||||
};
|
||||
|
||||
#define SCROLLER_ARROW_UP_WIDTH 9
|
||||
#define SCROLLER_ARROW_UP_HEIGHT 9
|
||||
|
||||
|
||||
static char *SCROLLER_ARROW_DOWN[] = {
|
||||
"%#######%",
|
||||
".#######.",
|
||||
".%#####%.",
|
||||
"..#####..",
|
||||
"..%###%..",
|
||||
"...###...",
|
||||
"...%#%...",
|
||||
"....#....",
|
||||
"....%...."
|
||||
};
|
||||
|
||||
static char *HI_SCROLLER_ARROW_DOWN[] = {
|
||||
"%%%%%%%%%",
|
||||
" %%%%%%% ",
|
||||
" %%%%%%% ",
|
||||
" %%%%% ",
|
||||
" %%%%% ",
|
||||
" %%% ",
|
||||
" %%% ",
|
||||
" % ",
|
||||
" % "
|
||||
};
|
||||
|
||||
#define SCROLLER_ARROW_DOWN_WIDTH 9
|
||||
#define SCROLLER_ARROW_DOWN_HEIGHT 9
|
||||
|
||||
|
||||
|
||||
static char *SCROLLER_ARROW_LEFT[] = {
|
||||
"........%",
|
||||
"......%##",
|
||||
"....%####",
|
||||
"..%######",
|
||||
"%########",
|
||||
"..%######",
|
||||
"....%####",
|
||||
"......%##",
|
||||
"........%"
|
||||
};
|
||||
|
||||
static char *HI_SCROLLER_ARROW_LEFT[] = {
|
||||
" %",
|
||||
" %%%",
|
||||
" %%%%%",
|
||||
" %%%%%%%",
|
||||
"%%%%%%%%%",
|
||||
" %%%%%%%",
|
||||
" %%%%%",
|
||||
" %%%",
|
||||
" %"
|
||||
};
|
||||
|
||||
#define SCROLLER_ARROW_LEFT_WIDTH 9
|
||||
#define SCROLLER_ARROW_LEFT_HEIGHT 9
|
||||
|
||||
|
||||
static char *SCROLLER_ARROW_RIGHT[] = {
|
||||
"%........",
|
||||
"##%......",
|
||||
"####%....",
|
||||
"######%..",
|
||||
"########%",
|
||||
"######%..",
|
||||
"####%....",
|
||||
"##%......",
|
||||
"%........"
|
||||
};
|
||||
|
||||
static char *HI_SCROLLER_ARROW_RIGHT[] = {
|
||||
"% ",
|
||||
"%%% ",
|
||||
"%%%%% ",
|
||||
"%%%%%%% ",
|
||||
"%%%%%%%%%",
|
||||
"%%%%%%% ",
|
||||
"%%%%% ",
|
||||
"%%% ",
|
||||
"% "
|
||||
};
|
||||
|
||||
#define SCROLLER_ARROW_RIGHT_WIDTH 9
|
||||
#define SCROLLER_ARROW_RIGHT_HEIGHT 9
|
||||
|
||||
|
||||
static char *POPUP_INDICATOR[] = {
|
||||
" #==",
|
||||
" ......%#==",
|
||||
" ......%#%%",
|
||||
" ......%#%%",
|
||||
" %%%%%%%#%%",
|
||||
"#########%%",
|
||||
"==%%%%%%%%%",
|
||||
"==%%%%%%%%%"
|
||||
};
|
||||
|
||||
#define POPUP_INDICATOR_WIDTH 11
|
||||
#define POPUP_INDICATOR_HEIGHT 8
|
||||
|
||||
|
||||
|
||||
static char *PULLDOWN_INDICATOR[] = {
|
||||
"=#######=",
|
||||
"=%===== =",
|
||||
"==%=== ==",
|
||||
"==%=== ==",
|
||||
"===%= ===",
|
||||
"===%= ===",
|
||||
"====%===="
|
||||
};
|
||||
#define PULLDOWN_INDICATOR_WIDTH 9
|
||||
#define PULLDOWN_INDICATOR_HEIGHT 7
|
||||
|
||||
|
||||
#define STIPPLE_WIDTH 8
|
||||
#define STIPPLE_HEIGHT 8
|
||||
static unsigned char STIPPLE_BITS[] = {
|
||||
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa};
|
||||
|
||||
|
||||
|
||||
extern W_ViewProcedureTable _WindowViewProcedures;
|
||||
extern W_ViewProcedureTable _FrameViewProcedures;
|
||||
extern W_ViewProcedureTable _LabelViewProcedures;
|
||||
extern W_ViewProcedureTable _ButtonViewProcedures;
|
||||
extern W_ViewProcedureTable _TextFieldViewProcedures;
|
||||
extern W_ViewProcedureTable _ScrollerViewProcedures;
|
||||
extern W_ViewProcedureTable _ScrollViewProcedures;
|
||||
extern W_ViewProcedureTable _ListViewProcedures;
|
||||
extern W_ViewProcedureTable _BrowserViewProcedures;
|
||||
extern W_ViewProcedureTable _PopUpButtonViewProcedures;
|
||||
extern W_ViewProcedureTable _ColorWellViewProcedures;
|
||||
extern W_ViewProcedureTable _ScrollViewViewProcedures;
|
||||
extern W_ViewProcedureTable _SliderViewProcedures;
|
||||
extern W_ViewProcedureTable _SplitViewViewProcedures;
|
||||
|
||||
/*
|
||||
* All widget classes defined must have an entry here.
|
||||
*/
|
||||
static W_ViewProcedureTable *procedureTables[16];
|
||||
|
||||
static W_ViewProcedureTable **userProcedureTable = NULL;
|
||||
static int userWidgetCount=0;
|
||||
|
||||
|
||||
/***** end data ******/
|
||||
|
||||
|
||||
|
||||
static void
|
||||
initProcedureTable()
|
||||
{
|
||||
procedureTables[WC_Window] = &_WindowViewProcedures;
|
||||
procedureTables[WC_Frame] = &_FrameViewProcedures;
|
||||
procedureTables[WC_Label] = &_LabelViewProcedures;
|
||||
procedureTables[WC_Button] = &_ButtonViewProcedures;
|
||||
procedureTables[WC_TextField] = &_TextFieldViewProcedures;
|
||||
procedureTables[WC_Scroller] = &_ScrollerViewProcedures;
|
||||
procedureTables[WC_List] = &_ListViewProcedures;
|
||||
procedureTables[WC_Browser] = &_BrowserViewProcedures;
|
||||
procedureTables[WC_PopUpButton] = &_PopUpButtonViewProcedures;
|
||||
procedureTables[WC_ColorWell] = &_ColorWellViewProcedures;
|
||||
procedureTables[WC_ScrollView] = &_ScrollViewViewProcedures;
|
||||
procedureTables[WC_Slider] = &_SliderViewProcedures;
|
||||
procedureTables[WC_SplitView] = &_SplitViewViewProcedures;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
renderPixmap(W_Screen *screen, Pixmap d, Pixmap mask, char **data,
|
||||
int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
GC whiteGC = W_GC(screen->white);
|
||||
GC blackGC = W_GC(screen->black);
|
||||
GC lightGC = W_GC(screen->gray);
|
||||
GC darkGC = W_GC(screen->darkGray);
|
||||
|
||||
|
||||
if (mask)
|
||||
XSetForeground(screen->display, screen->monoGC,
|
||||
W_PIXEL(screen->black));
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x++) {
|
||||
switch (data[y][x]) {
|
||||
case ' ':
|
||||
case 'w':
|
||||
XDrawPoint(screen->display, d, whiteGC, x, y);
|
||||
break;
|
||||
|
||||
case '=':
|
||||
if (mask)
|
||||
XDrawPoint(screen->display, mask, screen->monoGC, x, y);
|
||||
|
||||
case '.':
|
||||
case 'l':
|
||||
XDrawPoint(screen->display, d, lightGC, x, y);
|
||||
break;
|
||||
|
||||
case '%':
|
||||
case 'd':
|
||||
XDrawPoint(screen->display, d, darkGC, x, y);
|
||||
break;
|
||||
|
||||
case '#':
|
||||
case 'b':
|
||||
default:
|
||||
XDrawPoint(screen->display, d, blackGC, x, y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static WMPixmap*
|
||||
makePixmap(W_Screen *sPtr, char **data, int width, int height, int masked)
|
||||
{
|
||||
Pixmap pixmap, mask = None;
|
||||
|
||||
pixmap = XCreatePixmap(sPtr->display, W_DRAWABLE(sPtr), width, height,
|
||||
sPtr->depth);
|
||||
|
||||
if (masked) {
|
||||
mask = XCreatePixmap(sPtr->display, W_DRAWABLE(sPtr), width, height, 1);
|
||||
XSetForeground(sPtr->display, sPtr->monoGC, W_PIXEL(sPtr->white));
|
||||
XFillRectangle(sPtr->display, mask, sPtr->monoGC, 0, 0, width, height);
|
||||
}
|
||||
|
||||
renderPixmap(sPtr, pixmap, mask, data, width, height);
|
||||
|
||||
return WMCreatePixmapFromXPixmaps(sPtr, pixmap, mask, width, height,
|
||||
sPtr->depth);
|
||||
}
|
||||
|
||||
#ifdef USE_TIFF
|
||||
#define WINGS_IMAGES_FILE RESOURCE_PATH"/Images.tiff"
|
||||
#define DEFAULT_OBJECT_ICON_FILE RESOURCE_PATH"/defaultIcon.tiff"
|
||||
#else
|
||||
#define WINGS_IMAGES_FILE RESOURCE_PATH"/Images.xpm"
|
||||
#define DEFAULT_OBJECT_ICON_FILE RESOURCE_PATH"/defaultIcon.xpm"
|
||||
#endif
|
||||
|
||||
static Bool
|
||||
loadPixmaps(WMScreen *scr)
|
||||
{
|
||||
RImage *image, *tmp;
|
||||
Pixmap pixmap;
|
||||
RColor gray;
|
||||
|
||||
image = RLoadImage(scr->rcontext, WINGS_IMAGES_FILE, 0);
|
||||
if (!image) {
|
||||
wwarning("WINGs: could not load widget images file: %s", RErrorString);
|
||||
return False;
|
||||
}
|
||||
/* make it have a gray background */
|
||||
gray.red = 0xae;
|
||||
gray.green = 0xaa;
|
||||
gray.blue = 0xae;
|
||||
RCombineImageWithColor(image, &gray);
|
||||
tmp = RGetSubImage(image, 0, 0, 24, 24);
|
||||
if (!RConvertImage(scr->rcontext, tmp, &pixmap)) {
|
||||
scr->homeIcon = NULL;
|
||||
} else {
|
||||
scr->homeIcon = WMCreatePixmapFromXPixmaps(scr, pixmap, None, 24, 24,
|
||||
scr->depth);
|
||||
}
|
||||
RDestroyImage(tmp);
|
||||
RDestroyImage(image);
|
||||
|
||||
#if 0
|
||||
scr->defaultObjectIcon =
|
||||
WMCreatePixmapFromFile(scr, DEFAULT_OBJECT_ICON_FILE);
|
||||
if (!scr->defaultObjectIcon) {
|
||||
wwarning("WINGs: could not load default icon file");
|
||||
return False;
|
||||
}
|
||||
#endif
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMScreen*
|
||||
WMCreateSimpleApplicationScreen(Display *display)
|
||||
{
|
||||
WMScreen *scr;
|
||||
|
||||
scr = WMCreateScreen(display, DefaultScreen(display));
|
||||
|
||||
scr->aflags.hasAppIcon = 0;
|
||||
scr->aflags.simpleApplication = 1;
|
||||
|
||||
return scr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMScreen*
|
||||
WMCreateScreen(Display *display, int screen)
|
||||
{
|
||||
return WMCreateScreenWithRContext(display, screen,
|
||||
RCreateContext(display, screen, NULL));
|
||||
}
|
||||
|
||||
|
||||
WMScreen*
|
||||
WMCreateScreenWithRContext(Display *display, int screen, RContext *context)
|
||||
{
|
||||
W_Screen *scrPtr;
|
||||
XGCValues gcv;
|
||||
Pixmap stipple;
|
||||
static int initialized = 0;
|
||||
|
||||
if (!initialized) {
|
||||
|
||||
initialized = 1;
|
||||
|
||||
initProcedureTable();
|
||||
|
||||
assert(W_ApplicationInitialized());
|
||||
}
|
||||
|
||||
scrPtr = malloc(sizeof(W_Screen));
|
||||
if (!scrPtr)
|
||||
return NULL;
|
||||
memset(scrPtr, 0, sizeof(W_Screen));
|
||||
|
||||
scrPtr->aflags.hasAppIcon = 1;
|
||||
|
||||
scrPtr->display = display;
|
||||
scrPtr->screen = screen;
|
||||
scrPtr->rcontext = context;
|
||||
|
||||
scrPtr->depth = context->depth;
|
||||
|
||||
scrPtr->visual = context->visual;
|
||||
scrPtr->lastEventTime = 0;
|
||||
|
||||
scrPtr->colormap = context->cmap;
|
||||
|
||||
scrPtr->rootWin = RootWindow(display, screen);
|
||||
|
||||
|
||||
/* initially allocate some colors */
|
||||
WMWhiteColor(scrPtr);
|
||||
WMBlackColor(scrPtr);
|
||||
WMGrayColor(scrPtr);
|
||||
WMDarkGrayColor(scrPtr);
|
||||
|
||||
gcv.graphics_exposures = False;
|
||||
|
||||
gcv.function = GXxor;
|
||||
gcv.foreground = W_PIXEL(scrPtr->white);
|
||||
scrPtr->xorGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction
|
||||
|GCGraphicsExposures|GCForeground, &gcv);
|
||||
|
||||
gcv.function = GXxor;
|
||||
gcv.foreground = W_PIXEL(scrPtr->gray);
|
||||
gcv.subwindow_mode = IncludeInferiors;
|
||||
scrPtr->ixorGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction
|
||||
|GCGraphicsExposures|GCForeground
|
||||
|GCSubwindowMode, &gcv);
|
||||
|
||||
gcv.function = GXcopy;
|
||||
scrPtr->copyGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction
|
||||
|GCGraphicsExposures, &gcv);
|
||||
|
||||
scrPtr->clipGC = XCreateGC(display, W_DRAWABLE(scrPtr), GCFunction
|
||||
|GCGraphicsExposures, &gcv);
|
||||
|
||||
|
||||
stipple = XCreateBitmapFromData(display, W_DRAWABLE(scrPtr),
|
||||
STIPPLE_BITS, STIPPLE_WIDTH, STIPPLE_HEIGHT);
|
||||
gcv.foreground = W_PIXEL(scrPtr->darkGray);
|
||||
gcv.background = W_PIXEL(scrPtr->gray);
|
||||
gcv.fill_style = FillStippled;
|
||||
gcv.stipple = stipple;
|
||||
scrPtr->stippleGC = XCreateGC(display, W_DRAWABLE(scrPtr),
|
||||
GCForeground|GCBackground|GCStipple
|
||||
|GCFillStyle|GCGraphicsExposures, &gcv);
|
||||
|
||||
gcv.foreground = W_PIXEL(scrPtr->black);
|
||||
gcv.background = W_PIXEL(scrPtr->white);
|
||||
scrPtr->textFieldGC = XCreateGC(display, W_DRAWABLE(scrPtr),
|
||||
GCForeground|GCBackground, &gcv);
|
||||
|
||||
/* we need a 1bpp drawable for the monoGC, so borrow this one */
|
||||
scrPtr->monoGC = XCreateGC(display, stipple, 0, NULL);
|
||||
|
||||
XFreePixmap(display, stipple);
|
||||
|
||||
|
||||
scrPtr->normalFont = WMSystemFontOfSize(scrPtr, 12);
|
||||
|
||||
scrPtr->boldFont = WMBoldSystemFontOfSize(scrPtr, 12);
|
||||
|
||||
scrPtr->checkButtonImageOn = makePixmap(scrPtr, CHECK_BUTTON_ON,
|
||||
CHECK_BUTTON_ON_WIDTH,
|
||||
CHECK_BUTTON_ON_HEIGHT, False);
|
||||
|
||||
scrPtr->checkButtonImageOff = makePixmap(scrPtr, CHECK_BUTTON_OFF,
|
||||
CHECK_BUTTON_OFF_WIDTH,
|
||||
CHECK_BUTTON_OFF_HEIGHT, False);
|
||||
|
||||
scrPtr->radioButtonImageOn = makePixmap(scrPtr, RADIO_BUTTON_ON,
|
||||
RADIO_BUTTON_ON_WIDTH,
|
||||
RADIO_BUTTON_ON_HEIGHT, False);
|
||||
|
||||
scrPtr->radioButtonImageOff = makePixmap(scrPtr, RADIO_BUTTON_OFF,
|
||||
RADIO_BUTTON_OFF_WIDTH,
|
||||
RADIO_BUTTON_OFF_HEIGHT, False);
|
||||
|
||||
scrPtr->buttonArrow = makePixmap(scrPtr, BUTTON_ARROW,
|
||||
BUTTON_ARROW_WIDTH, BUTTON_ARROW_HEIGHT,
|
||||
False);
|
||||
|
||||
scrPtr->pushedButtonArrow = makePixmap(scrPtr, BUTTON_ARROW2,
|
||||
BUTTON_ARROW2_WIDTH, BUTTON_ARROW2_HEIGHT,
|
||||
False);
|
||||
|
||||
|
||||
scrPtr->scrollerDimple = makePixmap(scrPtr, SCROLLER_DIMPLE,
|
||||
SCROLLER_DIMPLE_WIDTH,
|
||||
SCROLLER_DIMPLE_HEIGHT, False);
|
||||
|
||||
|
||||
scrPtr->upArrow = makePixmap(scrPtr, SCROLLER_ARROW_UP,
|
||||
SCROLLER_ARROW_UP_WIDTH,
|
||||
SCROLLER_ARROW_UP_HEIGHT, True);
|
||||
|
||||
scrPtr->downArrow = makePixmap(scrPtr, SCROLLER_ARROW_DOWN,
|
||||
SCROLLER_ARROW_DOWN_WIDTH,
|
||||
SCROLLER_ARROW_DOWN_HEIGHT, True);
|
||||
|
||||
scrPtr->leftArrow = makePixmap(scrPtr, SCROLLER_ARROW_LEFT,
|
||||
SCROLLER_ARROW_LEFT_WIDTH,
|
||||
SCROLLER_ARROW_LEFT_HEIGHT, True);
|
||||
|
||||
scrPtr->rightArrow = makePixmap(scrPtr, SCROLLER_ARROW_RIGHT,
|
||||
SCROLLER_ARROW_RIGHT_WIDTH,
|
||||
SCROLLER_ARROW_RIGHT_HEIGHT, True);
|
||||
|
||||
scrPtr->hiUpArrow = makePixmap(scrPtr, HI_SCROLLER_ARROW_UP,
|
||||
SCROLLER_ARROW_UP_WIDTH,
|
||||
SCROLLER_ARROW_UP_HEIGHT, True);
|
||||
|
||||
scrPtr->hiDownArrow = makePixmap(scrPtr, HI_SCROLLER_ARROW_DOWN,
|
||||
SCROLLER_ARROW_DOWN_WIDTH,
|
||||
SCROLLER_ARROW_DOWN_HEIGHT, True);
|
||||
|
||||
scrPtr->hiLeftArrow = makePixmap(scrPtr, HI_SCROLLER_ARROW_LEFT,
|
||||
SCROLLER_ARROW_LEFT_WIDTH,
|
||||
SCROLLER_ARROW_LEFT_HEIGHT, True);
|
||||
|
||||
scrPtr->hiRightArrow = makePixmap(scrPtr, HI_SCROLLER_ARROW_RIGHT,
|
||||
SCROLLER_ARROW_RIGHT_WIDTH,
|
||||
SCROLLER_ARROW_RIGHT_HEIGHT, True);
|
||||
|
||||
scrPtr->popUpIndicator = makePixmap(scrPtr, POPUP_INDICATOR,
|
||||
POPUP_INDICATOR_WIDTH,
|
||||
POPUP_INDICATOR_HEIGHT, True);
|
||||
|
||||
scrPtr->pullDownIndicator = makePixmap(scrPtr, PULLDOWN_INDICATOR,
|
||||
PULLDOWN_INDICATOR_WIDTH,
|
||||
PULLDOWN_INDICATOR_HEIGHT, True);
|
||||
loadPixmaps(scrPtr);
|
||||
|
||||
scrPtr->defaultCursor = XCreateFontCursor(display, XC_left_ptr);
|
||||
|
||||
scrPtr->textCursor = XCreateFontCursor(display, XC_xterm);
|
||||
|
||||
scrPtr->internalMessage = XInternAtom(display, "_WINGS_MESSAGE", False);
|
||||
|
||||
scrPtr->attribsAtom = XInternAtom(display, "_GNUSTEP_WM_ATTR", False);
|
||||
|
||||
scrPtr->deleteWindowAtom = XInternAtom(display, "WM_DELETE_WINDOW", False);
|
||||
|
||||
scrPtr->protocolsAtom = XInternAtom(display, "WM_PROTOCOLS", False);
|
||||
|
||||
scrPtr->clipboardAtom = XInternAtom(display, "CLIPBOARD", False);
|
||||
|
||||
scrPtr->rootView = W_CreateRootView(scrPtr);
|
||||
|
||||
return scrPtr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMHangData(WMWidget *widget, void *data)
|
||||
{
|
||||
W_VIEW(widget)->hangedData = data;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
WMGetHangedData(WMWidget *widget)
|
||||
{
|
||||
return W_VIEW(widget)->hangedData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMDestroyWidget(WMWidget *widget)
|
||||
{
|
||||
W_DestroyView(W_VIEW(widget));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetFocusToWidget(WMWidget *widget)
|
||||
{
|
||||
W_SetFocusOfTopLevel(W_TopLevelOfView(W_VIEW(widget)), W_VIEW(widget));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* WMRealizeWidget-
|
||||
* Realizes the widget and all it's children.
|
||||
*
|
||||
*/
|
||||
void
|
||||
WMRealizeWidget(WMWidget *w)
|
||||
{
|
||||
W_RealizeView(W_VIEW(w));
|
||||
}
|
||||
|
||||
void
|
||||
WMMapWidget(WMWidget *w)
|
||||
{
|
||||
W_MapView(W_VIEW(w));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
makeChildrenAutomap(W_View *view, int flag)
|
||||
{
|
||||
view = view->childrenList;
|
||||
|
||||
while (view) {
|
||||
view->flags.mapWhenRealized = flag;
|
||||
makeChildrenAutomap(view, flag);
|
||||
|
||||
view = view->nextSister;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMMapSubwidgets(WMWidget *w)
|
||||
{
|
||||
/* make sure that subwidgets created after the parent was realized
|
||||
* are mapped too */
|
||||
if (!W_VIEW(w)->flags.realized) {
|
||||
makeChildrenAutomap(W_VIEW(w), True);
|
||||
} else {
|
||||
W_MapSubviews(W_VIEW(w));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMUnmapSubwidgets(WMWidget *w)
|
||||
{
|
||||
if (!W_VIEW(w)->flags.realized) {
|
||||
makeChildrenAutomap(W_VIEW(w), False);
|
||||
} else {
|
||||
W_UnmapSubviews(W_VIEW(w));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMUnmapWidget(WMWidget *w)
|
||||
{
|
||||
W_UnmapView(W_VIEW(w));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetWidgetBackgroundColor(WMWidget *w, WMColor *color)
|
||||
{
|
||||
if (W_CLASS(w) < WC_UserWidget
|
||||
&& procedureTables[W_CLASS(w)]->setBackgroundColor) {
|
||||
|
||||
(*procedureTables[W_CLASS(w)]->setBackgroundColor)(w, color);
|
||||
|
||||
} else if (W_CLASS(w) >= WC_UserWidget
|
||||
&& userProcedureTable[W_CLASS(w)-WC_UserWidget]->setBackgroundColor) {
|
||||
|
||||
(*userProcedureTable[W_CLASS(w)-WC_UserWidget]->setBackgroundColor)(w, color);
|
||||
|
||||
} else {
|
||||
W_SetViewBackgroundColor(W_VIEW(w), color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMMoveWidget(WMWidget *w, int x, int y)
|
||||
{
|
||||
if (W_CLASS(w) < WC_UserWidget
|
||||
&& procedureTables[W_CLASS(w)]->move) {
|
||||
|
||||
(*procedureTables[W_CLASS(w)]->move)(w, x, y);
|
||||
|
||||
} else if (W_CLASS(w) >= WC_UserWidget
|
||||
&& userProcedureTable[W_CLASS(w)-WC_UserWidget]->move) {
|
||||
|
||||
(*userProcedureTable[W_CLASS(w)-WC_UserWidget]->move)(w, x, y);
|
||||
|
||||
} else {
|
||||
W_MoveView(W_VIEW(w), x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMResizeWidget(WMWidget *w, unsigned int width, unsigned int height)
|
||||
{
|
||||
if (W_CLASS(w) < WC_UserWidget
|
||||
&& procedureTables[W_CLASS(w)]->resize) {
|
||||
|
||||
(*procedureTables[W_CLASS(w)]->resize)(w, width, height);
|
||||
|
||||
} else if (W_CLASS(w) >= WC_UserWidget
|
||||
&& userProcedureTable[W_CLASS(w)-WC_UserWidget]->resize) {
|
||||
|
||||
(*userProcedureTable[W_CLASS(w)-WC_UserWidget]->resize)(w, width, height);
|
||||
|
||||
} else {
|
||||
W_ResizeView(W_VIEW(w), width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
W_Class
|
||||
W_RegisterUserWidget(W_ViewProcedureTable *procTable)
|
||||
{
|
||||
W_ViewProcedureTable **newTable;
|
||||
|
||||
userWidgetCount++;
|
||||
newTable = wmalloc(sizeof(W_ViewProcedureTable*)*userWidgetCount);
|
||||
memcpy(newTable, userProcedureTable,
|
||||
sizeof(W_ViewProcedureTable*)*(userWidgetCount-1));
|
||||
|
||||
newTable[userWidgetCount-1] = procTable;
|
||||
|
||||
free(userProcedureTable);
|
||||
|
||||
userProcedureTable = newTable;
|
||||
|
||||
return userWidgetCount + WC_UserWidget - 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
RContext*
|
||||
WMScreenRContext(WMScreen *scr)
|
||||
{
|
||||
return scr->rcontext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int
|
||||
WMWidgetWidth(WMWidget *w)
|
||||
{
|
||||
return W_VIEW(w)->size.width;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
WMWidgetHeight(WMWidget *w)
|
||||
{
|
||||
return W_VIEW(w)->size.height;
|
||||
}
|
||||
|
||||
|
||||
Window
|
||||
WMWidgetXID(WMWidget *w)
|
||||
{
|
||||
return W_VIEW(w)->window;
|
||||
}
|
||||
|
||||
|
||||
WMScreen*
|
||||
WMWidgetScreen(WMWidget *w)
|
||||
{
|
||||
return W_VIEW(w)->screen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMScreenMainLoop(WMScreen *scr)
|
||||
{
|
||||
XEvent event;
|
||||
|
||||
while (1) {
|
||||
WMNextEvent(scr->display, &event);
|
||||
WMHandleEvent(&event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Display*
|
||||
WMScreenDisplay(WMScreen *scr)
|
||||
{
|
||||
return scr->display;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMRedisplayWidget(WMWidget *w)
|
||||
{
|
||||
W_RedisplayView(W_VIEW(w));
|
||||
}
|
||||
|
||||
243
WINGs/wlabel.c
Normal file
243
WINGs/wlabel.c
Normal file
@@ -0,0 +1,243 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
|
||||
typedef struct W_Label {
|
||||
W_Class widgetClass;
|
||||
W_View *view;
|
||||
|
||||
char *caption;
|
||||
|
||||
WMColor *textColor;
|
||||
WMFont *font; /* if NULL, use default */
|
||||
|
||||
W_Pixmap *image;
|
||||
|
||||
struct {
|
||||
WMReliefType relief:3;
|
||||
WMImagePosition imagePosition:4;
|
||||
WMAlignment alignment:2;
|
||||
|
||||
unsigned int noWrap:1;
|
||||
|
||||
unsigned int redrawPending:1;
|
||||
} flags;
|
||||
} Label;
|
||||
|
||||
|
||||
|
||||
W_ViewProcedureTable _LabelViewProcedures = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#define DEFAULT_WIDTH 60
|
||||
#define DEFAULT_HEIGHT 14
|
||||
#define DEFAULT_ALIGNMENT WALeft
|
||||
#define DEFAULT_RELIEF WRFlat
|
||||
#define DEFAULT_IMAGE_POSITION WIPNoImage
|
||||
|
||||
|
||||
static void destroyLabel(Label *lPtr);
|
||||
static void paintLabel(Label *lPtr);
|
||||
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
|
||||
|
||||
WMLabel*
|
||||
WMCreateLabel(WMWidget *parent)
|
||||
{
|
||||
Label *lPtr;
|
||||
|
||||
lPtr = wmalloc(sizeof(Label));
|
||||
memset(lPtr, 0, sizeof(Label));
|
||||
|
||||
lPtr->widgetClass = WC_Label;
|
||||
|
||||
lPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!lPtr->view) {
|
||||
free(lPtr);
|
||||
return NULL;
|
||||
}
|
||||
lPtr->view->self = lPtr;
|
||||
|
||||
lPtr->textColor = WMRetainColor(lPtr->view->screen->black);
|
||||
|
||||
WMCreateEventHandler(lPtr->view, ExposureMask|StructureNotifyMask,
|
||||
handleEvents, lPtr);
|
||||
|
||||
W_ResizeView(lPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
lPtr->flags.alignment = DEFAULT_ALIGNMENT;
|
||||
lPtr->flags.relief = DEFAULT_RELIEF;
|
||||
lPtr->flags.imagePosition = DEFAULT_IMAGE_POSITION;
|
||||
|
||||
return lPtr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetLabelImage(WMLabel *lPtr, WMPixmap *image)
|
||||
{
|
||||
if (lPtr->image!=NULL)
|
||||
WMReleasePixmap(lPtr->image);
|
||||
|
||||
if (image)
|
||||
lPtr->image = WMRetainPixmap(image);
|
||||
else
|
||||
lPtr->image = NULL;
|
||||
|
||||
if (lPtr->view->flags.realized) {
|
||||
paintLabel(lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetLabelImagePosition(WMLabel *lPtr, WMImagePosition position)
|
||||
{
|
||||
lPtr->flags.imagePosition = position;
|
||||
if (lPtr->view->flags.realized) {
|
||||
paintLabel(lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetLabelTextAlignment(WMLabel *lPtr, WMAlignment alignment)
|
||||
{
|
||||
lPtr->flags.alignment = alignment;
|
||||
if (lPtr->view->flags.realized) {
|
||||
paintLabel(lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetLabelRelief(WMLabel *lPtr, WMReliefType relief)
|
||||
{
|
||||
lPtr->flags.relief = relief;
|
||||
if (lPtr->view->flags.realized) {
|
||||
paintLabel(lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetLabelText(WMLabel *lPtr, char *text)
|
||||
{
|
||||
if (lPtr->caption)
|
||||
free(lPtr->caption);
|
||||
|
||||
if (text!=NULL) {
|
||||
lPtr->caption = wstrdup(text);
|
||||
} else {
|
||||
lPtr->caption = NULL;
|
||||
}
|
||||
if (lPtr->view->flags.realized) {
|
||||
paintLabel(lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetLabelFont(WMLabel *lPtr, WMFont *font)
|
||||
{
|
||||
if (lPtr->font!=NULL)
|
||||
WMReleaseFont(lPtr->font);
|
||||
if (font)
|
||||
lPtr->font = WMRetainFont(font);
|
||||
else
|
||||
lPtr->font = NULL;
|
||||
|
||||
if (lPtr->view->flags.realized) {
|
||||
paintLabel(lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetLabelTextColor(WMLabel *lPtr, WMColor *color)
|
||||
{
|
||||
if (lPtr->textColor)
|
||||
WMReleaseColor(lPtr->textColor);
|
||||
lPtr->textColor = WMRetainColor(color);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetLabelWraps(WMLabel *lPtr, Bool flag)
|
||||
{
|
||||
if (lPtr->flags.noWrap != !flag) {
|
||||
lPtr->flags.noWrap = !flag;
|
||||
if (lPtr->view->flags.realized)
|
||||
paintLabel(lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintLabel(Label *lPtr)
|
||||
{
|
||||
W_Screen *scrPtr = lPtr->view->screen;
|
||||
GC gc;
|
||||
|
||||
if (lPtr->textColor)
|
||||
gc = W_GC(lPtr->textColor);
|
||||
else
|
||||
gc = W_GC(scrPtr->black);
|
||||
|
||||
W_PaintTextAndImage(lPtr->view, !lPtr->flags.noWrap, gc,
|
||||
(lPtr->font!=NULL ? lPtr->font : scrPtr->normalFont),
|
||||
lPtr->flags.relief, lPtr->caption,
|
||||
lPtr->flags.alignment, lPtr->image,
|
||||
lPtr->flags.imagePosition, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
Label *lPtr = (Label*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_Label);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintLabel(lPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyLabel(lPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
destroyLabel(Label *lPtr)
|
||||
{
|
||||
if (lPtr->textColor)
|
||||
WMReleaseColor(lPtr->textColor);
|
||||
|
||||
if (lPtr->caption)
|
||||
free(lPtr->caption);
|
||||
|
||||
if (lPtr->font)
|
||||
WMReleaseFont(lPtr->font);
|
||||
|
||||
if (lPtr->image)
|
||||
WMReleasePixmap(lPtr->image);
|
||||
|
||||
free(lPtr);
|
||||
}
|
||||
797
WINGs/wlist.c
Normal file
797
WINGs/wlist.c
Normal file
@@ -0,0 +1,797 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
typedef struct W_List {
|
||||
W_Class widgetClass;
|
||||
W_View *view;
|
||||
|
||||
WMListItem *items; /* array of items */
|
||||
short itemCount;
|
||||
|
||||
short selectedItem;
|
||||
|
||||
short itemHeight;
|
||||
|
||||
short topItem; /* index of first visible item */
|
||||
|
||||
short fullFitLines; /* no of lines that fit entirely */
|
||||
|
||||
void *clientData;
|
||||
WMAction *action;
|
||||
void *doubleClientData;
|
||||
WMAction *doubleAction;
|
||||
|
||||
WMListDrawProc *draw;
|
||||
|
||||
WMHandlerID *idleID; /* for updating the scroller after
|
||||
* adding elements */
|
||||
|
||||
WMScroller *vScroller;
|
||||
/*
|
||||
WMScroller *hScroller;
|
||||
*/
|
||||
|
||||
struct {
|
||||
unsigned int allowMultipleSelection:1;
|
||||
unsigned int userDrawn:1;
|
||||
unsigned int userItemHeight:1;
|
||||
/* */
|
||||
unsigned int dontFitAll:1; /* 1 = last item won't be fully visible */
|
||||
unsigned int redrawPending:1;
|
||||
unsigned int buttonPressed:1;
|
||||
unsigned int buttonWasPressed:1;
|
||||
} flags;
|
||||
} List;
|
||||
|
||||
|
||||
|
||||
#define DEFAULT_WIDTH 150
|
||||
#define DEFAULT_HEIGHT 150
|
||||
|
||||
|
||||
static void destroyList(List *lPtr);
|
||||
static void paintList(List *lPtr);
|
||||
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleActionEvents(XEvent *event, void *data);
|
||||
static void updateScroller(List *lPtr);
|
||||
|
||||
static void vScrollCallBack(WMWidget *scroller, void *self);
|
||||
|
||||
static void resizeList();
|
||||
|
||||
|
||||
W_ViewProcedureTable _ListViewProcedures = {
|
||||
NULL,
|
||||
resizeList,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
WMList*
|
||||
WMCreateList(WMWidget *parent)
|
||||
{
|
||||
List *lPtr;
|
||||
W_Screen *scrPtr = W_VIEW(parent)->screen;
|
||||
|
||||
lPtr = wmalloc(sizeof(List));
|
||||
memset(lPtr, 0, sizeof(List));
|
||||
|
||||
lPtr->widgetClass = WC_List;
|
||||
|
||||
lPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!lPtr->view) {
|
||||
free(lPtr);
|
||||
return NULL;
|
||||
}
|
||||
lPtr->view->self = lPtr;
|
||||
|
||||
WMCreateEventHandler(lPtr->view, ExposureMask|StructureNotifyMask
|
||||
|ClientMessageMask, handleEvents, lPtr);
|
||||
|
||||
WMCreateEventHandler(lPtr->view, ButtonPressMask|ButtonReleaseMask
|
||||
|EnterWindowMask|LeaveWindowMask|ButtonMotionMask,
|
||||
handleActionEvents, lPtr);
|
||||
|
||||
lPtr->itemHeight = scrPtr->normalFont->height + 1;
|
||||
|
||||
/* create the vertical scroller */
|
||||
lPtr->vScroller = WMCreateScroller(lPtr);
|
||||
WMMoveWidget(lPtr->vScroller, 1, 1);
|
||||
WMSetScrollerArrowsPosition(lPtr->vScroller, WSAMaxEnd);
|
||||
|
||||
WMSetScrollerAction(lPtr->vScroller, vScrollCallBack, lPtr);
|
||||
|
||||
/* make the scroller map itself when it's realized */
|
||||
WMMapWidget(lPtr->vScroller);
|
||||
|
||||
resizeList(lPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
||||
lPtr->selectedItem = -1;
|
||||
|
||||
return lPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMListItem*
|
||||
WMAddSortedListItem(WMList *lPtr, char *text)
|
||||
{
|
||||
WMListItem *item;
|
||||
WMListItem *tmp;
|
||||
int index;
|
||||
|
||||
item = wmalloc(sizeof(WMListItem));
|
||||
memset(item, 0, sizeof(WMListItem));
|
||||
item->text = wstrdup(text);
|
||||
if (!lPtr->items) {
|
||||
lPtr->items = item;
|
||||
index = 0;
|
||||
} else if (strcmp(lPtr->items->text, text) > 0) {
|
||||
item->nextPtr = lPtr->items;
|
||||
lPtr->items = item;
|
||||
index = 1;
|
||||
} else {
|
||||
int added = 0;
|
||||
|
||||
index = 0;
|
||||
tmp = lPtr->items;
|
||||
while (tmp->nextPtr) {
|
||||
if (strcmp(tmp->nextPtr->text, text) >= 0) {
|
||||
item->nextPtr = tmp->nextPtr;
|
||||
tmp->nextPtr = item;
|
||||
added = 1;
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
tmp = tmp->nextPtr;
|
||||
}
|
||||
if (!added) {
|
||||
tmp->nextPtr = item;
|
||||
}
|
||||
}
|
||||
|
||||
lPtr->itemCount++;
|
||||
|
||||
if (lPtr->selectedItem >= index)
|
||||
lPtr->selectedItem++;
|
||||
|
||||
/* update the scroller when idle, so that we don't waste time
|
||||
* updating it when another item is going to be added later */
|
||||
if (!lPtr->idleID) {
|
||||
lPtr->idleID = WMAddIdleHandler((WMCallback*)updateScroller, lPtr);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMListItem*
|
||||
WMInsertListItem(WMList *lPtr, int row, char *text)
|
||||
{
|
||||
WMListItem *item;
|
||||
WMListItem *tmp = lPtr->items;
|
||||
|
||||
CHECK_CLASS(lPtr, WC_List);
|
||||
|
||||
item = wmalloc(sizeof(WMListItem));
|
||||
memset(item, 0, sizeof(WMListItem));
|
||||
item->text = wstrdup(text);
|
||||
|
||||
if (lPtr->selectedItem >= row && lPtr->selectedItem >= 0)
|
||||
lPtr->selectedItem++;
|
||||
|
||||
if (lPtr->items==NULL) {
|
||||
lPtr->items = item;
|
||||
} else if (row == 0) {
|
||||
item->nextPtr = lPtr->items;
|
||||
lPtr->items = item;
|
||||
} else if (row < 0) {
|
||||
while (tmp->nextPtr)
|
||||
tmp = tmp->nextPtr;
|
||||
|
||||
tmp->nextPtr = item;
|
||||
row = lPtr->itemCount;
|
||||
} else {
|
||||
while (--row > 0)
|
||||
tmp = tmp->nextPtr;
|
||||
|
||||
item->nextPtr = tmp->nextPtr;
|
||||
tmp->nextPtr = item;
|
||||
}
|
||||
|
||||
lPtr->itemCount++;
|
||||
|
||||
/* update the scroller when idle, so that we don't waste time
|
||||
* updating it when another item is going to be added later */
|
||||
if (!lPtr->idleID) {
|
||||
lPtr->idleID = WMAddIdleHandler((WMCallback*)updateScroller, lPtr);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMRemoveListItem(WMList *lPtr, int row)
|
||||
{
|
||||
WMListItem *llist;
|
||||
WMListItem *tmp;
|
||||
|
||||
CHECK_CLASS(lPtr, WC_List);
|
||||
|
||||
if (row < 0 || row >= lPtr->itemCount)
|
||||
return;
|
||||
|
||||
if (lPtr->selectedItem == row)
|
||||
lPtr->selectedItem = -1;
|
||||
else if (lPtr->selectedItem > row)
|
||||
lPtr->selectedItem--;
|
||||
|
||||
if (row <= lPtr->topItem+lPtr->fullFitLines+lPtr->flags.dontFitAll)
|
||||
lPtr->topItem--;
|
||||
if (lPtr->topItem < 0)
|
||||
lPtr->topItem = 0;
|
||||
|
||||
if (row == 0) {
|
||||
if (lPtr->items->text)
|
||||
free(lPtr->items->text);
|
||||
|
||||
tmp = lPtr->items->nextPtr;
|
||||
free(lPtr->items);
|
||||
|
||||
lPtr->items = tmp;
|
||||
} else {
|
||||
llist = lPtr->items;
|
||||
while (--row > 0)
|
||||
llist = llist->nextPtr;
|
||||
tmp = llist->nextPtr;
|
||||
llist->nextPtr = llist->nextPtr->nextPtr;
|
||||
|
||||
if (tmp->text)
|
||||
free(tmp->text);
|
||||
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
lPtr->itemCount--;
|
||||
|
||||
if (!lPtr->idleID) {
|
||||
lPtr->idleID = WMAddIdleHandler((WMCallback*)updateScroller, lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMListItem*
|
||||
WMGetListItem(WMList *lPtr, int row)
|
||||
{
|
||||
WMListItem *listPtr;
|
||||
|
||||
listPtr = lPtr->items;
|
||||
|
||||
while (row-- > 0)
|
||||
listPtr = listPtr->nextPtr;
|
||||
|
||||
return listPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetListUserDrawProc(WMList *lPtr, WMListDrawProc *proc)
|
||||
{
|
||||
lPtr->flags.userDrawn = 1;
|
||||
lPtr->draw = proc;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetListUserDrawItemHeight(WMList *lPtr, unsigned short height)
|
||||
{
|
||||
assert(height > 0);
|
||||
|
||||
lPtr->flags.userItemHeight = 1;
|
||||
lPtr->itemHeight = height;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMClearList(WMList *lPtr)
|
||||
{
|
||||
WMListItem *item, *tmp;
|
||||
|
||||
item = lPtr->items;
|
||||
while (item) {
|
||||
free(item->text);
|
||||
tmp = item->nextPtr;
|
||||
free(item);
|
||||
item = tmp;
|
||||
}
|
||||
lPtr->items = NULL;
|
||||
lPtr->itemCount = 0;
|
||||
lPtr->topItem = 0;
|
||||
lPtr->selectedItem = -1;
|
||||
|
||||
if (!lPtr->idleID) {
|
||||
WMDeleteIdleHandler(lPtr->idleID);
|
||||
lPtr->idleID = NULL;
|
||||
}
|
||||
if (lPtr->view->flags.realized) {
|
||||
updateScroller(lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetListAction(WMList *lPtr, WMAction *action, void *clientData)
|
||||
{
|
||||
lPtr->action = action;
|
||||
lPtr->clientData = clientData;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetListDoubleAction(WMList *lPtr, WMAction *action, void *clientData)
|
||||
{
|
||||
lPtr->doubleAction = action;
|
||||
lPtr->doubleClientData = clientData;
|
||||
}
|
||||
|
||||
|
||||
WMListItem*
|
||||
WMGetListSelectedItem(WMList *lPtr)
|
||||
{
|
||||
int i = lPtr->selectedItem;
|
||||
WMListItem *item;
|
||||
|
||||
if (lPtr->selectedItem < 0)
|
||||
return NULL;
|
||||
|
||||
item = lPtr->items;
|
||||
while (i-- > 0) {
|
||||
item = item->nextPtr;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetListSelectedItemRow(WMList *lPtr)
|
||||
{
|
||||
return lPtr->selectedItem;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetListPosition(WMList *lPtr, int row)
|
||||
{
|
||||
lPtr->topItem = row;
|
||||
if (lPtr->topItem + lPtr->fullFitLines > lPtr->itemCount)
|
||||
lPtr->topItem = lPtr->itemCount - lPtr->fullFitLines;
|
||||
|
||||
if (lPtr->topItem < 0)
|
||||
lPtr->topItem = 0;
|
||||
|
||||
if (lPtr->view->flags.realized)
|
||||
updateScroller(lPtr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetListBottomPosition(WMList *lPtr, int row)
|
||||
{
|
||||
if (lPtr->itemCount > lPtr->fullFitLines) {
|
||||
lPtr->topItem = row - lPtr->fullFitLines;
|
||||
if (lPtr->topItem < 0)
|
||||
lPtr->topItem = 0;
|
||||
if (lPtr->view->flags.realized)
|
||||
updateScroller(lPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetListNumberOfRows(WMList *lPtr)
|
||||
{
|
||||
return lPtr->itemCount;
|
||||
}
|
||||
|
||||
int
|
||||
WMGetListPosition(WMList *lPtr)
|
||||
{
|
||||
return lPtr->topItem;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
vScrollCallBack(WMWidget *scroller, void *self)
|
||||
{
|
||||
WMList *lPtr = (WMList*)self;
|
||||
WMScroller *sPtr = (WMScroller*)scroller;
|
||||
int height;
|
||||
|
||||
height = lPtr->view->size.height - 4;
|
||||
|
||||
switch (WMGetScrollerHitPart(sPtr)) {
|
||||
case WSDecrementLine:
|
||||
if (lPtr->topItem > 0) {
|
||||
lPtr->topItem--;
|
||||
|
||||
updateScroller(lPtr);
|
||||
}
|
||||
break;
|
||||
|
||||
case WSDecrementPage:
|
||||
if (lPtr->topItem > 0) {
|
||||
lPtr->topItem -= lPtr->fullFitLines-(1-lPtr->flags.dontFitAll)-1;
|
||||
if (lPtr->topItem < 0)
|
||||
lPtr->topItem = 0;
|
||||
|
||||
updateScroller(lPtr);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case WSIncrementLine:
|
||||
if (lPtr->topItem + lPtr->fullFitLines < lPtr->itemCount) {
|
||||
lPtr->topItem++;
|
||||
|
||||
updateScroller(lPtr);
|
||||
}
|
||||
break;
|
||||
|
||||
case WSIncrementPage:
|
||||
if (lPtr->topItem + lPtr->fullFitLines < lPtr->itemCount) {
|
||||
lPtr->topItem += lPtr->fullFitLines-(1-lPtr->flags.dontFitAll)-1;
|
||||
|
||||
if (lPtr->topItem + lPtr->fullFitLines > lPtr->itemCount)
|
||||
lPtr->topItem = lPtr->itemCount - lPtr->fullFitLines;
|
||||
|
||||
updateScroller(lPtr);
|
||||
}
|
||||
break;
|
||||
|
||||
case WSKnob:
|
||||
{
|
||||
int oldTopItem = lPtr->topItem;
|
||||
|
||||
lPtr->topItem = WMGetScrollerValue(lPtr->vScroller) *
|
||||
(float)(lPtr->itemCount - lPtr->fullFitLines);
|
||||
|
||||
if (oldTopItem != lPtr->topItem)
|
||||
paintList(lPtr);
|
||||
}
|
||||
break;
|
||||
|
||||
case WSKnobSlot:
|
||||
case WSNoPart:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintItem(List *lPtr, int index)
|
||||
{
|
||||
WMView *view = lPtr->view;
|
||||
W_Screen *scr = view->screen;
|
||||
int width, height, x, y;
|
||||
WMListItem *itemPtr;
|
||||
int i;
|
||||
|
||||
i = index;
|
||||
itemPtr = lPtr->items;
|
||||
while (i-- > 0)
|
||||
itemPtr = itemPtr->nextPtr;
|
||||
|
||||
width = lPtr->view->size.width - 2 - 19;
|
||||
height = lPtr->itemHeight;
|
||||
x = 19;
|
||||
y = 2 + (index-lPtr->topItem) * lPtr->itemHeight + 1;
|
||||
|
||||
if (lPtr->flags.userDrawn) {
|
||||
WMRect rect;
|
||||
int flags;
|
||||
|
||||
rect.size.width = width;
|
||||
rect.size.height = height;
|
||||
rect.pos.x = x;
|
||||
rect.pos.y = y;
|
||||
|
||||
flags = itemPtr->uflags;
|
||||
if (itemPtr->disabled)
|
||||
flags |= WLDSDisabled;
|
||||
if (itemPtr->selected)
|
||||
flags |= WLDSSelected;
|
||||
if (itemPtr->isBranch)
|
||||
flags |= WLDSIsBranch;
|
||||
|
||||
if (lPtr->draw)
|
||||
(*lPtr->draw)(lPtr, view->window, itemPtr->text, flags, &rect);
|
||||
|
||||
} else {
|
||||
if (itemPtr->selected)
|
||||
XFillRectangle(scr->display, view->window, W_GC(scr->white), x, y,
|
||||
width, height);
|
||||
else
|
||||
XClearArea(scr->display, view->window, x, y, width, height, False);
|
||||
|
||||
W_PaintText(view, view->window, scr->normalFont, x+4, y, width,
|
||||
WALeft, W_GC(scr->black), False,
|
||||
itemPtr->text, strlen(itemPtr->text));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
paintList(List *lPtr)
|
||||
{
|
||||
W_Screen *scrPtr = lPtr->view->screen;
|
||||
int i, lim;
|
||||
|
||||
if (!lPtr->view->flags.mapped)
|
||||
return;
|
||||
|
||||
if (lPtr->itemCount>0) {
|
||||
if (lPtr->topItem+lPtr->fullFitLines+lPtr->flags.dontFitAll > lPtr->itemCount) {
|
||||
lim = lPtr->itemCount - lPtr->topItem;
|
||||
XClearArea(scrPtr->display, lPtr->view->window, 19,
|
||||
2+lim*lPtr->itemHeight, lPtr->view->size.width-21,
|
||||
lPtr->view->size.height-lim*lPtr->itemHeight-3, False);
|
||||
} else {
|
||||
lim = lPtr->fullFitLines + lPtr->flags.dontFitAll;
|
||||
}
|
||||
for (i = lPtr->topItem; i < lPtr->topItem + lim; i++) {
|
||||
paintItem(lPtr, i);
|
||||
}
|
||||
} else {
|
||||
XClearWindow(scrPtr->display, lPtr->view->window);
|
||||
}
|
||||
W_DrawRelief(scrPtr, lPtr->view->window, 0, 0, lPtr->view->size.width,
|
||||
lPtr->view->size.height, WRSunken);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
scrollTo(List *lPtr, int newTop)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
updateScroller(List *lPtr)
|
||||
{
|
||||
float knobProportion, floatValue, tmp;
|
||||
|
||||
if (lPtr->idleID)
|
||||
WMDeleteIdleHandler(lPtr->idleID);
|
||||
lPtr->idleID = NULL;
|
||||
|
||||
paintList(lPtr);
|
||||
|
||||
if (lPtr->itemCount == 0 || lPtr->itemCount <= lPtr->fullFitLines)
|
||||
WMSetScrollerParameters(lPtr->vScroller, 0, 1);
|
||||
else {
|
||||
tmp = lPtr->fullFitLines;
|
||||
knobProportion = tmp/(float)lPtr->itemCount;
|
||||
|
||||
floatValue = (float)lPtr->topItem/(float)(lPtr->itemCount - lPtr->fullFitLines);
|
||||
|
||||
WMSetScrollerParameters(lPtr->vScroller, floatValue, knobProportion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
List *lPtr = (List*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_List);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintList(lPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyList(lPtr);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMFindRowOfListItemWithTitle(WMList *lPtr, char *title)
|
||||
{
|
||||
WMListItem *item;
|
||||
int i;
|
||||
int ok = 0;
|
||||
|
||||
for (i=0, item=lPtr->items; item!=NULL; item=item->nextPtr, i++) {
|
||||
if (strcmp(item->text, title)==0) {
|
||||
ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ok ? i : -1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSelectListItem(WMList *lPtr, int row)
|
||||
{
|
||||
WMListItem *itemPtr;
|
||||
int i;
|
||||
|
||||
if (row >= lPtr->itemCount)
|
||||
return;
|
||||
|
||||
if (!lPtr->flags.allowMultipleSelection) {
|
||||
/* unselect previous selected item */
|
||||
if (lPtr->selectedItem >= 0) {
|
||||
itemPtr = lPtr->items;
|
||||
for (i=0; i<lPtr->selectedItem; i++)
|
||||
itemPtr = itemPtr->nextPtr;
|
||||
|
||||
if (itemPtr->selected) {
|
||||
itemPtr->selected = 0;
|
||||
if (lPtr->view->flags.mapped && i>=lPtr->topItem
|
||||
&& i<=lPtr->topItem+lPtr->fullFitLines)
|
||||
paintItem(lPtr, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (row < 0) {
|
||||
if (!lPtr->flags.allowMultipleSelection)
|
||||
lPtr->selectedItem = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* select item */
|
||||
itemPtr = lPtr->items;
|
||||
for (i=0; i<row; i++)
|
||||
itemPtr = itemPtr->nextPtr;
|
||||
if (lPtr->flags.allowMultipleSelection)
|
||||
itemPtr->selected = !itemPtr->selected;
|
||||
else
|
||||
itemPtr->selected = 1;
|
||||
|
||||
if (lPtr->view->flags.mapped) {
|
||||
paintItem(lPtr, row);
|
||||
|
||||
if ((row-lPtr->topItem+lPtr->fullFitLines)*lPtr->itemHeight
|
||||
> lPtr->view->size.height-2)
|
||||
W_DrawRelief(lPtr->view->screen, lPtr->view->window, 0, 0,
|
||||
lPtr->view->size.width, lPtr->view->size.height,
|
||||
WRSunken);
|
||||
}
|
||||
lPtr->selectedItem = row;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
getItemIndexAt(List *lPtr, int clickY)
|
||||
{
|
||||
int index;
|
||||
|
||||
index = (clickY - 2) / lPtr->itemHeight + lPtr->topItem;
|
||||
|
||||
if (index < 0 || index >= lPtr->itemCount)
|
||||
return -1;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
List *lPtr = (List*)data;
|
||||
int tmp;
|
||||
|
||||
CHECK_CLASS(data, WC_List);
|
||||
|
||||
switch (event->type) {
|
||||
case ButtonRelease:
|
||||
lPtr->flags.buttonPressed = 0;
|
||||
tmp = getItemIndexAt(lPtr, event->xbutton.y);
|
||||
if (tmp == lPtr->selectedItem && tmp >= 0) {
|
||||
if (WMIsDoubleClick(event)) {
|
||||
if (lPtr->doubleAction)
|
||||
(*lPtr->doubleAction)(lPtr, lPtr->doubleClientData);
|
||||
} else {
|
||||
if (lPtr->action)
|
||||
(*lPtr->action)(lPtr, lPtr->clientData);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EnterNotify:
|
||||
lPtr->flags.buttonPressed = lPtr->flags.buttonWasPressed;
|
||||
lPtr->flags.buttonWasPressed = 0;
|
||||
break;
|
||||
|
||||
case LeaveNotify:
|
||||
lPtr->flags.buttonWasPressed = lPtr->flags.buttonPressed;
|
||||
lPtr->flags.buttonPressed = 0;
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
if (event->xbutton.x > WMWidgetWidth(lPtr->vScroller)) {
|
||||
tmp = getItemIndexAt(lPtr, event->xbutton.y);
|
||||
|
||||
if (tmp>=0) {
|
||||
WMSelectListItem(lPtr, tmp);
|
||||
lPtr->selectedItem = tmp;
|
||||
}
|
||||
lPtr->flags.buttonPressed = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
if (lPtr->flags.buttonPressed) {
|
||||
tmp = getItemIndexAt(lPtr, event->xmotion.y);
|
||||
if (tmp>=0 && tmp != lPtr->selectedItem) {
|
||||
WMSelectListItem(lPtr, tmp);
|
||||
lPtr->selectedItem = tmp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resizeList(WMList *lPtr, unsigned int width, unsigned int height)
|
||||
{
|
||||
W_ResizeView(lPtr->view, width, height);
|
||||
|
||||
WMResizeWidget(lPtr->vScroller, 1, height-2);
|
||||
|
||||
lPtr->fullFitLines = (height - 4) / lPtr->itemHeight;
|
||||
if (lPtr->fullFitLines * lPtr->itemHeight < height-4) {
|
||||
lPtr->flags.dontFitAll = 1;
|
||||
} else {
|
||||
lPtr->flags.dontFitAll = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
destroyList(List *lPtr)
|
||||
{
|
||||
WMListItem *itemPtr;
|
||||
|
||||
if (lPtr->idleID)
|
||||
WMDeleteIdleHandler(lPtr->idleID);
|
||||
lPtr->idleID = NULL;
|
||||
|
||||
while (lPtr->items!=NULL) {
|
||||
itemPtr = lPtr->items;
|
||||
if (itemPtr->text)
|
||||
free(itemPtr->text);
|
||||
|
||||
lPtr->items = itemPtr->nextPtr;
|
||||
free(itemPtr);
|
||||
}
|
||||
|
||||
free(lPtr);
|
||||
}
|
||||
97
WINGs/wmfile.c
Normal file
97
WINGs/wmfile.c
Normal file
@@ -0,0 +1,97 @@
|
||||
|
||||
/*
|
||||
* Author: Len Trigg <trigg@cs.waikato.ac.nz>
|
||||
*/
|
||||
|
||||
|
||||
#include "WINGs.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "logo.xpm"
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
wAbort()
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *ProgName;
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage:\n"
|
||||
"\t%s [-options]\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -i <str>\tInitial directory (default /)\n"
|
||||
" -t <str>\tQuery window title (default none)\n"
|
||||
"\n"
|
||||
"information:\n"
|
||||
"\t%s pops up a WindowMaker style file selection panel.\n"
|
||||
"\n"
|
||||
"version:\n"
|
||||
"\t%s\n"
|
||||
,ProgName,ProgName,__DATE__
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Display *dpy = XOpenDisplay("");
|
||||
WMScreen *scr;
|
||||
WMPixmap *pixmap;
|
||||
WMOpenPanel *panel;
|
||||
/* RImage *image;*/
|
||||
char *title = NULL;
|
||||
char *initial = "/";
|
||||
int ch;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
WMInitializeApplication("WMFile", &argc, argv);
|
||||
|
||||
ProgName = argv[0];
|
||||
|
||||
if (!dpy) {
|
||||
puts("could not open display");
|
||||
exit(1);
|
||||
}
|
||||
while((ch = getopt(argc, argv, "i:ht:")) != -1)
|
||||
switch(ch)
|
||||
{
|
||||
case 'i':
|
||||
initial = optarg;
|
||||
break;
|
||||
case 't':
|
||||
title = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
for(; optind <argc; optind++)
|
||||
usage();
|
||||
|
||||
scr = WMCreateSimpleApplicationScreen(dpy);
|
||||
|
||||
|
||||
|
||||
pixmap = WMCreatePixmapFromXPMData(scr, GNUSTEP_XPM);
|
||||
WMSetApplicationIconImage(scr, pixmap); WMReleasePixmap(pixmap);
|
||||
panel = WMGetOpenPanel(scr);
|
||||
|
||||
/* The 3rd argument for this function is the initial name of the file,
|
||||
* not the name of the window, although it's not implemented yet */
|
||||
if (WMRunModalOpenPanelForDirectory(panel, NULL, initial, /*title*/ NULL, NULL) == True)
|
||||
printf("%s\n", WMGetFilePanelFileName(panel));
|
||||
else
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
297
WINGs/wmisc.c
Normal file
297
WINGs/wmisc.c
Normal file
@@ -0,0 +1,297 @@
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <wraster.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
void
|
||||
W_DrawRelief(W_Screen *scr, Drawable d, int x, int y, unsigned int width,
|
||||
unsigned int height, WMReliefType relief)
|
||||
{
|
||||
Display *dpy = scr->display;
|
||||
GC bgc;
|
||||
GC wgc;
|
||||
GC lgc;
|
||||
GC dgc;
|
||||
|
||||
switch (relief) {
|
||||
case WRSimple:
|
||||
XDrawRectangle(dpy, d, W_GC(scr->black), x, y, width-1, height-1);
|
||||
return;
|
||||
break;
|
||||
|
||||
case WRRaised:
|
||||
bgc = W_GC(scr->black);
|
||||
dgc = W_GC(scr->darkGray);
|
||||
wgc = W_GC(scr->white);
|
||||
lgc = W_GC(scr->gray);
|
||||
break;
|
||||
|
||||
case WRSunken:
|
||||
wgc = W_GC(scr->darkGray);
|
||||
lgc = W_GC(scr->black);
|
||||
bgc = W_GC(scr->white);
|
||||
dgc = W_GC(scr->gray);
|
||||
break;
|
||||
|
||||
case WRPushed:
|
||||
lgc = wgc = W_GC(scr->black);
|
||||
dgc = bgc = W_GC(scr->white);
|
||||
break;
|
||||
|
||||
case WRRidge:
|
||||
lgc = bgc = W_GC(scr->darkGray);
|
||||
dgc = wgc = W_GC(scr->white);
|
||||
break;
|
||||
|
||||
case WRGroove:
|
||||
wgc = dgc = W_GC(scr->darkGray);
|
||||
lgc = bgc = W_GC(scr->white);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
/* top left */
|
||||
XDrawLine(dpy, d, wgc, x, y, x+width-1, y);
|
||||
if (width > 2 && relief != WRRaised && relief!=WRPushed) {
|
||||
XDrawLine(dpy, d, lgc, x+1, y+1, x+width-3, y+1);
|
||||
}
|
||||
|
||||
XDrawLine(dpy, d, wgc, x, y, x, y+height-1);
|
||||
if (height > 2 && relief != WRRaised && relief!=WRPushed) {
|
||||
XDrawLine(dpy, d, lgc, x+1, y+1, x+1, y+height-3);
|
||||
}
|
||||
|
||||
/* bottom right */
|
||||
XDrawLine(dpy, d, bgc, x, y+height-1, x+width-1, y+height-1);
|
||||
if (width > 2 && relief!=WRPushed) {
|
||||
XDrawLine(dpy, d, dgc, x+1, y+height-2, x+width-2, y+height-2);
|
||||
}
|
||||
|
||||
XDrawLine(dpy, d, bgc, x+width-1, y, x+width-1, y+height-1);
|
||||
if (height > 2 && relief!=WRPushed) {
|
||||
XDrawLine(dpy, d, dgc, x+width-2, y+2, x+width-2, y+height-3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fitText(char *text, WMFont *font, int width, int wrap)
|
||||
{
|
||||
int i, j;
|
||||
int w;
|
||||
|
||||
if (text[0]==0)
|
||||
return 0;
|
||||
i = 0;
|
||||
if (wrap) {
|
||||
do {
|
||||
i++;
|
||||
w = WMWidthOfString(font, text, i);
|
||||
} while (w < width && text[i]!='\n' && text[i]!=0);
|
||||
|
||||
/* keep words complete */
|
||||
if (!isspace(text[i])) {
|
||||
j = i;
|
||||
while (j>1 && !isspace(text[j]) && text[j]!=0)
|
||||
j--;
|
||||
if (j>1)
|
||||
i = j;
|
||||
}
|
||||
} else {
|
||||
while (text[i]!='\n' && text[i]!=0)
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
W_GetTextHeight(WMFont *font, char *text, int width, int wrap)
|
||||
{
|
||||
char *ptr = text;
|
||||
int count;
|
||||
int length = strlen(text);
|
||||
int h;
|
||||
|
||||
h = 0;
|
||||
while (length > 0) {
|
||||
count = fitText(ptr, font, width, wrap);
|
||||
|
||||
h += font->height;
|
||||
|
||||
if (isspace(ptr[count]))
|
||||
count++;
|
||||
|
||||
ptr += count;
|
||||
length -= count;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_PaintText(W_View *view, Drawable d, WMFont *font, int x, int y,
|
||||
int width, WMAlignment alignment, GC gc,
|
||||
int wrap, char *text, int length)
|
||||
{
|
||||
char *ptr = text;
|
||||
int line_width;
|
||||
int line_x;
|
||||
int count;
|
||||
|
||||
while (length > 0) {
|
||||
count = fitText(ptr, font, width, wrap);
|
||||
|
||||
line_width = WMWidthOfString(font, ptr, count);
|
||||
if (alignment==WALeft)
|
||||
line_x = x;
|
||||
else if (alignment==WARight)
|
||||
line_x = x + width - line_width;
|
||||
else
|
||||
line_x = x + (width - line_width) / 2;
|
||||
|
||||
WMDrawString(view->screen, d, gc, font, line_x, y, ptr, count);
|
||||
|
||||
y += font->height;
|
||||
|
||||
if (isspace(ptr[count]))
|
||||
count++;
|
||||
|
||||
ptr += count;
|
||||
length -= count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_PaintTextAndImage(W_View *view, int wrap, GC textGC, W_Font *font,
|
||||
WMReliefType relief, char *text,
|
||||
WMAlignment alignment, W_Pixmap *image,
|
||||
WMImagePosition position, GC backGC, int ofs)
|
||||
{
|
||||
W_Screen *screen = view->screen;
|
||||
int ix, iy;
|
||||
int x, y, w, h;
|
||||
Drawable d = view->window;
|
||||
|
||||
|
||||
#ifdef DOUBLE_BUFFER
|
||||
d = XCreatePixmap(screen->display, view->window,
|
||||
view->size.width, view->size.height, screen->depth);
|
||||
#endif
|
||||
|
||||
/* background */
|
||||
#ifndef DOUBLE_BUFFER
|
||||
if (backGC) {
|
||||
XFillRectangle(screen->display, d, backGC,
|
||||
0, 0, view->size.width, view->size.height);
|
||||
} else {
|
||||
XClearWindow(screen->display, d);
|
||||
}
|
||||
#else
|
||||
if (backGC)
|
||||
XFillRectangle(screen->display, d, backGC, 0, 0,
|
||||
view->size.width, view->size.height);
|
||||
else {
|
||||
XSetForeground(screen->display, screen->copyGC,
|
||||
view->attribs.background_pixel);
|
||||
XFillRectangle(screen->display, d, screen->copyGC, 0, 0,
|
||||
view->size.width, view->size.height);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (relief == WRFlat) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = view->size.width;
|
||||
h = view->size.height;
|
||||
} else {
|
||||
x = 2;
|
||||
y = 2;
|
||||
w = view->size.width - 4;
|
||||
h = view->size.height - 4;
|
||||
}
|
||||
|
||||
/* calc. image alignment */
|
||||
if (position!=WIPNoImage && image!=NULL) {
|
||||
switch (position) {
|
||||
case WIPOverlaps:
|
||||
case WIPImageOnly:
|
||||
ix = (view->size.width - image->width) / 2;
|
||||
iy = (view->size.height - image->height) / 2;
|
||||
/*
|
||||
x = 2;
|
||||
y = 0;
|
||||
*/
|
||||
break;
|
||||
|
||||
case WIPLeft:
|
||||
ix = x;
|
||||
iy = y + (h - image->height) / 2;
|
||||
x = x + image->width + 5;
|
||||
y = 0;
|
||||
w -= image->width + 5;
|
||||
break;
|
||||
|
||||
case WIPRight:
|
||||
ix = view->size.width - image->width - x;
|
||||
iy = y + (h - image->height) / 2;
|
||||
w -= image->width + 5;
|
||||
break;
|
||||
|
||||
case WIPBelow:
|
||||
ix = (view->size.width - image->width) / 2;
|
||||
iy = h - image->height;
|
||||
y = 0;
|
||||
h -= image->height;
|
||||
break;
|
||||
|
||||
default:
|
||||
case WIPAbove:
|
||||
ix = (view->size.width - image->width) / 2;
|
||||
iy = y;
|
||||
y = image->height;
|
||||
h -= image->height;
|
||||
break;
|
||||
}
|
||||
|
||||
ix += ofs;
|
||||
iy += ofs;
|
||||
|
||||
XSetClipOrigin(screen->display, screen->clipGC, ix, iy);
|
||||
XSetClipMask(screen->display, screen->clipGC, image->mask);
|
||||
|
||||
if (image->depth==1)
|
||||
XCopyPlane(screen->display, image->pixmap, d, screen->clipGC,
|
||||
0, 0, image->width, image->height, ix, iy, 1);
|
||||
else
|
||||
XCopyArea(screen->display, image->pixmap, d, screen->clipGC,
|
||||
0, 0, image->width, image->height, ix, iy);
|
||||
}
|
||||
|
||||
/* draw text */
|
||||
if (position != WIPImageOnly && text!=NULL) {
|
||||
int textHeight;
|
||||
|
||||
textHeight = W_GetTextHeight(font, text, w-8, wrap);
|
||||
W_PaintText(view, d, font, x+ofs+4, y+ofs + (h-textHeight)/2, w-8,
|
||||
alignment, textGC, wrap, text, strlen(text));
|
||||
}
|
||||
|
||||
|
||||
/* draw relief */
|
||||
W_DrawRelief(screen, d, 0, 0, view->size.width, view->size.height, relief);
|
||||
|
||||
#ifdef DOUBLE_BUFFER
|
||||
XCopyArea(screen->display, d, view->window, screen->copyGC, 0, 0,
|
||||
view->size.width, view->size.height, 0, 0);
|
||||
XFreePixmap(screen->display, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
99
WINGs/wmquery.c
Normal file
99
WINGs/wmquery.c
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
/*
|
||||
* Author: Len Trigg <trigg@cs.waikato.ac.nz>
|
||||
*/
|
||||
|
||||
|
||||
#include "WINGs.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "logo.xpm"
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
wAbort()
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *ProgName;
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage:\n"
|
||||
"\t%s [-options]\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -i <str>\tInitial entry contents (default none)\n"
|
||||
" -p <str>\tPrompt message (default none)\n"
|
||||
" -t <str>\tQuery window title (default none)\n"
|
||||
"\n"
|
||||
"information:\n"
|
||||
"\t%s pops up a WindowMaker style input panel.\n"
|
||||
"\n"
|
||||
"version:\n"
|
||||
"\t%s\n"
|
||||
,ProgName,ProgName,__DATE__
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Display *dpy = XOpenDisplay("");
|
||||
WMScreen *scr;
|
||||
WMPixmap *pixmap;
|
||||
char *title = NULL;
|
||||
char *prompt = NULL;
|
||||
char *initial = NULL;
|
||||
char *result = NULL;
|
||||
int ch;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
WMInitializeApplication("WMQuery", &argc, argv);
|
||||
|
||||
ProgName = argv[0];
|
||||
|
||||
if (!dpy) {
|
||||
puts("could not open display");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while((ch = getopt(argc, argv, "i:hp:t:")) != -1)
|
||||
switch(ch)
|
||||
{
|
||||
case 'i':
|
||||
initial = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
prompt = optarg;
|
||||
break;
|
||||
case 't':
|
||||
title = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
for(; optind <argc; optind++)
|
||||
usage();
|
||||
|
||||
|
||||
scr = WMCreateSimpleApplicationScreen(dpy);
|
||||
|
||||
pixmap = WMCreatePixmapFromXPMData(scr, GNUSTEP_XPM);
|
||||
|
||||
WMSetApplicationIconImage(scr, pixmap); WMReleasePixmap(pixmap);
|
||||
|
||||
if ((result = WMRunInputPanel(scr, NULL, title, prompt, initial, "OK", "Cancel")) != NULL)
|
||||
printf("%s\n", result);
|
||||
else
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
399
WINGs/wpanel.c
Normal file
399
WINGs/wpanel.c
Normal file
@@ -0,0 +1,399 @@
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <X11/keysym.h>
|
||||
|
||||
|
||||
|
||||
static void
|
||||
alertPanelOnClick(WMWidget *self, void *clientData)
|
||||
{
|
||||
WMAlertPanel *panel = clientData;
|
||||
|
||||
panel->done = 1;
|
||||
if (self == panel->defBtn) {
|
||||
panel->result = WAPRDefault;
|
||||
} else if (self == panel->othBtn) {
|
||||
panel->result = WAPROther;
|
||||
} else if (self == panel->altBtn) {
|
||||
panel->result = WAPRAlternate;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleKeyPress(XEvent *event, void *clientData)
|
||||
{
|
||||
WMAlertPanel *panel = (WMAlertPanel*)clientData;
|
||||
|
||||
if (event->xkey.keycode == panel->retKey) {
|
||||
WMPerformButtonClick(panel->defBtn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMRunAlertPanel(WMScreen *scrPtr, WMWindow *owner,
|
||||
char *title, char *msg, char *defaultButton,
|
||||
char *alternateButton, char *otherButton)
|
||||
{
|
||||
WMAlertPanel *panel;
|
||||
int tmp;
|
||||
|
||||
panel = WMCreateAlertPanel(scrPtr, owner, title, msg, defaultButton,
|
||||
alternateButton, otherButton);
|
||||
|
||||
scrPtr->modalView = W_VIEW(panel->win);
|
||||
WMMapWidget(panel->win);
|
||||
|
||||
scrPtr->modal = 1;
|
||||
while (!panel->done || WMScreenPending(scrPtr)) {
|
||||
XEvent event;
|
||||
|
||||
WMNextEvent(scrPtr->display, &event);
|
||||
WMHandleEvent(&event);
|
||||
}
|
||||
scrPtr->modal = 0;
|
||||
|
||||
tmp = panel->result;
|
||||
|
||||
WMDestroyAlertPanel(panel);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMDestroyAlertPanel(WMAlertPanel *panel)
|
||||
{
|
||||
WMUnmapWidget(panel->win);
|
||||
WMDestroyWidget(panel->win);
|
||||
free(panel);
|
||||
}
|
||||
|
||||
|
||||
WMAlertPanel*
|
||||
WMCreateAlertPanel(WMScreen *scrPtr, WMWindow *owner,
|
||||
char *title, char *msg, char *defaultButton,
|
||||
char *alternateButton, char *otherButton)
|
||||
{
|
||||
WMAlertPanel *panel;
|
||||
int x, dw=0, aw=0, ow=0, w;
|
||||
|
||||
|
||||
panel = wmalloc(sizeof(WMAlertPanel));
|
||||
memset(panel, 0, sizeof(WMAlertPanel));
|
||||
|
||||
|
||||
panel->retKey = XKeysymToKeycode(scrPtr->display, XK_Return);
|
||||
|
||||
if (owner)
|
||||
panel->win = WMCreatePanelWithStyleForWindow(owner, "alertPanel",
|
||||
WMTitledWindowMask);
|
||||
else
|
||||
panel->win = WMCreateWindowWithStyle(scrPtr, "alertPanel",
|
||||
WMTitledWindowMask);
|
||||
|
||||
WMSetWindowTitle(panel->win, "");
|
||||
|
||||
if (scrPtr->applicationIcon) {
|
||||
panel->iLbl = WMCreateLabel(panel->win);
|
||||
WMResizeWidget(panel->iLbl, scrPtr->applicationIcon->width,
|
||||
scrPtr->applicationIcon->height);
|
||||
WMMoveWidget(panel->iLbl, 8 + (64 - scrPtr->applicationIcon->width)/2,
|
||||
(75 - scrPtr->applicationIcon->height)/2);
|
||||
WMSetLabelImage(panel->iLbl, scrPtr->applicationIcon);
|
||||
WMSetLabelImagePosition(panel->iLbl, WIPImageOnly);
|
||||
}
|
||||
|
||||
if (title) {
|
||||
WMFont *largeFont;
|
||||
|
||||
largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
|
||||
|
||||
panel->tLbl = WMCreateLabel(panel->win);
|
||||
WMMoveWidget(panel->tLbl, 80, (80 - largeFont->height)/2);
|
||||
WMResizeWidget(panel->tLbl, 400 - 70, largeFont->height+4);
|
||||
WMSetLabelText(panel->tLbl, title);
|
||||
WMSetLabelTextAlignment(panel->tLbl, WALeft);
|
||||
WMSetLabelFont(panel->tLbl, largeFont);
|
||||
|
||||
WMReleaseFont(largeFont);
|
||||
}
|
||||
|
||||
|
||||
if (msg) {
|
||||
panel->mLbl = WMCreateLabel(panel->win);
|
||||
WMMoveWidget(panel->mLbl, 10, 83);
|
||||
WMResizeWidget(panel->mLbl, 380, scrPtr->normalFont->height*4);
|
||||
WMSetLabelText(panel->mLbl, msg);
|
||||
WMSetLabelTextAlignment(panel->mLbl, WACenter);
|
||||
}
|
||||
|
||||
|
||||
/* create divider line */
|
||||
|
||||
panel->line = WMCreateFrame(panel->win);
|
||||
WMMoveWidget(panel->line, 0, 80);
|
||||
WMResizeWidget(panel->line, 400, 2);
|
||||
WMSetFrameRelief(panel->line, WRGroove);
|
||||
|
||||
/* create buttons */
|
||||
if (otherButton)
|
||||
ow = WMWidthOfString(scrPtr->normalFont, otherButton,
|
||||
strlen(otherButton));
|
||||
|
||||
if (alternateButton)
|
||||
aw = WMWidthOfString(scrPtr->normalFont, alternateButton,
|
||||
strlen(alternateButton));
|
||||
|
||||
if (defaultButton)
|
||||
dw = WMWidthOfString(scrPtr->normalFont, defaultButton,
|
||||
strlen(defaultButton));
|
||||
|
||||
w = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);
|
||||
if (aw > w)
|
||||
w = aw;
|
||||
if (ow > w)
|
||||
w = ow;
|
||||
|
||||
w += 30;
|
||||
x = 400;
|
||||
|
||||
if (defaultButton) {
|
||||
x -= w + 10;
|
||||
|
||||
panel->defBtn = WMCreateCommandButton(panel->win);
|
||||
WMSetButtonAction(panel->defBtn, alertPanelOnClick, panel);
|
||||
WMMoveWidget(panel->defBtn, x, 144);
|
||||
WMResizeWidget(panel->defBtn, w, 24);
|
||||
WMSetButtonText(panel->defBtn, defaultButton);
|
||||
WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
|
||||
WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
|
||||
WMSetButtonImagePosition(panel->defBtn, WIPRight);
|
||||
}
|
||||
if (alternateButton) {
|
||||
x -= w + 10;
|
||||
|
||||
panel->altBtn = WMCreateCommandButton(panel->win);
|
||||
WMMoveWidget(panel->altBtn, x, 144);
|
||||
WMResizeWidget(panel->altBtn, w, 24);
|
||||
WMSetButtonAction(panel->altBtn, alertPanelOnClick, panel);
|
||||
WMSetButtonText(panel->altBtn, alternateButton);
|
||||
}
|
||||
if (otherButton) {
|
||||
x -= w + 10;
|
||||
|
||||
panel->othBtn = WMCreateCommandButton(panel->win);
|
||||
WMSetButtonAction(panel->othBtn, alertPanelOnClick, panel);
|
||||
WMMoveWidget(panel->othBtn, x, 144);
|
||||
WMResizeWidget(panel->othBtn, w, 24);
|
||||
WMSetButtonText(panel->othBtn, otherButton);
|
||||
}
|
||||
|
||||
panel->done = 0;
|
||||
|
||||
WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask,
|
||||
handleKeyPress, panel);
|
||||
|
||||
WMRealizeWidget(panel->win);
|
||||
WMMapSubwidgets(panel->win);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
inputBoxOnClick(WMWidget *self, void *clientData)
|
||||
{
|
||||
WMInputPanel *panel = clientData;
|
||||
|
||||
panel->done = 1;
|
||||
if (self == panel->defBtn) {
|
||||
panel->result = WAPRDefault;
|
||||
} else if (self == panel->altBtn) {
|
||||
panel->result = WAPRAlternate;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleKeyPress2(XEvent *event, void *clientData)
|
||||
{
|
||||
WMInputPanel *panel = (WMInputPanel*)clientData;
|
||||
|
||||
if (event->xkey.keycode == panel->retKey) {
|
||||
WMPerformButtonClick(panel->defBtn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMRunInputPanel(WMScreen *scrPtr, WMWindow *owner, char *title,
|
||||
char *msg, char *defaultText,
|
||||
char *okButton, char *cancelButton)
|
||||
{
|
||||
WMInputPanel *panel;
|
||||
char *tmp;
|
||||
|
||||
panel = WMCreateInputPanel(scrPtr, owner, title, msg, defaultText,
|
||||
okButton, cancelButton);
|
||||
|
||||
WMMapWidget(panel->win);
|
||||
|
||||
while (!panel->done || WMScreenPending(scrPtr)) {
|
||||
XEvent event;
|
||||
|
||||
WMNextEvent(scrPtr->display, &event);
|
||||
WMHandleEvent(&event);
|
||||
}
|
||||
|
||||
|
||||
if (panel->result == WAPRDefault)
|
||||
tmp = WMGetTextFieldText(panel->text);
|
||||
else
|
||||
tmp = NULL;
|
||||
|
||||
WMDestroyInputPanel(panel);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMDestroyInputPanel(WMInputPanel *panel)
|
||||
{
|
||||
WMRemoveNotificationObserver(panel);
|
||||
WMUnmapWidget(panel->win);
|
||||
WMDestroyWidget(panel->win);
|
||||
free(panel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
endedEditingObserver(void *observerData, WMNotification *notification)
|
||||
{
|
||||
WMInputPanel *panel = (WMInputPanel*)observerData;
|
||||
|
||||
if ((int)WMGetNotificationClientData(notification) == WMReturnTextMovement) {
|
||||
WMPerformButtonClick(panel->defBtn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMInputPanel*
|
||||
WMCreateInputPanel(WMScreen *scrPtr, WMWindow *owner, char *title, char *msg,
|
||||
char *defaultText, char *okButton, char *cancelButton)
|
||||
{
|
||||
WMInputPanel *panel;
|
||||
int x, dw=0, aw=0, w;
|
||||
|
||||
|
||||
panel = wmalloc(sizeof(WMInputPanel));
|
||||
memset(panel, 0, sizeof(WMInputPanel));
|
||||
|
||||
panel->retKey = XKeysymToKeycode(scrPtr->display, XK_Return);
|
||||
|
||||
if (owner)
|
||||
panel->win = WMCreatePanelWithStyleForWindow(owner, "inputPanel",
|
||||
WMTitledWindowMask);
|
||||
else
|
||||
panel->win = WMCreateWindowWithStyle(scrPtr, "inputPanel",
|
||||
WMTitledWindowMask);
|
||||
WMSetWindowTitle(panel->win, "");
|
||||
|
||||
WMResizeWidget(panel->win, 320, 160);
|
||||
|
||||
if (title) {
|
||||
WMFont *largeFont;
|
||||
|
||||
largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
|
||||
|
||||
panel->tLbl = WMCreateLabel(panel->win);
|
||||
WMMoveWidget(panel->tLbl, 20, 16);
|
||||
WMResizeWidget(panel->tLbl, 320 - 40, largeFont->height+4);
|
||||
WMSetLabelText(panel->tLbl, title);
|
||||
WMSetLabelTextAlignment(panel->tLbl, WALeft);
|
||||
WMSetLabelFont(panel->tLbl, largeFont);
|
||||
|
||||
WMReleaseFont(largeFont);
|
||||
}
|
||||
|
||||
|
||||
if (msg) {
|
||||
panel->mLbl = WMCreateLabel(panel->win);
|
||||
WMMoveWidget(panel->mLbl, 20, 50);
|
||||
WMResizeWidget(panel->mLbl, 320 - 40,scrPtr->normalFont->height*2);
|
||||
WMSetLabelText(panel->mLbl, msg);
|
||||
WMSetLabelTextAlignment(panel->mLbl, WALeft);
|
||||
}
|
||||
|
||||
panel->text = WMCreateTextField(panel->win);
|
||||
WMMoveWidget(panel->text, 20, 85);
|
||||
WMResizeWidget(panel->text, 320 - 40, WMWidgetHeight(panel->text));
|
||||
WMSetTextFieldText(panel->text, defaultText);
|
||||
|
||||
WMAddNotificationObserver(endedEditingObserver, panel,
|
||||
WMTextDidEndEditingNotification, panel->text);
|
||||
|
||||
/* create buttons */
|
||||
if (cancelButton)
|
||||
aw = WMWidthOfString(scrPtr->normalFont, cancelButton,
|
||||
strlen(cancelButton));
|
||||
|
||||
if (okButton)
|
||||
dw = WMWidthOfString(scrPtr->normalFont, okButton,
|
||||
strlen(okButton));
|
||||
|
||||
w = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);
|
||||
if (aw > w)
|
||||
w = aw;
|
||||
|
||||
w += 30;
|
||||
x = 310;
|
||||
|
||||
if (okButton) {
|
||||
x -= w + 10;
|
||||
|
||||
panel->defBtn = WMCreateCustomButton(panel->win, WBBPushInMask
|
||||
|WBBPushChangeMask
|
||||
|WBBPushLightMask);
|
||||
WMSetButtonAction(panel->defBtn, inputBoxOnClick, panel);
|
||||
WMMoveWidget(panel->defBtn, x, 124);
|
||||
WMResizeWidget(panel->defBtn, w, 24);
|
||||
WMSetButtonText(panel->defBtn, okButton);
|
||||
WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
|
||||
WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
|
||||
WMSetButtonImagePosition(panel->defBtn, WIPRight);
|
||||
}
|
||||
if (cancelButton) {
|
||||
x -= w + 10;
|
||||
|
||||
panel->altBtn = WMCreateCommandButton(panel->win);
|
||||
WMSetButtonAction(panel->altBtn, inputBoxOnClick, panel);
|
||||
WMMoveWidget(panel->altBtn, x, 124);
|
||||
WMResizeWidget(panel->altBtn, w, 24);
|
||||
WMSetButtonText(panel->altBtn, cancelButton);
|
||||
}
|
||||
|
||||
panel->done = 0;
|
||||
|
||||
WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask,
|
||||
handleKeyPress2, panel);
|
||||
|
||||
WMRealizeWidget(panel->win);
|
||||
WMMapSubwidgets(panel->win);
|
||||
|
||||
WMSetFocusToWidget(panel->text);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
205
WINGs/wpixmap.c
Normal file
205
WINGs/wpixmap.c
Normal file
@@ -0,0 +1,205 @@
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <wraster.h>
|
||||
|
||||
|
||||
WMPixmap*
|
||||
WMRetainPixmap(WMPixmap *pixmap)
|
||||
{
|
||||
if (pixmap)
|
||||
pixmap->refCount++;
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMReleasePixmap(WMPixmap *pixmap)
|
||||
{
|
||||
pixmap->refCount--;
|
||||
|
||||
if (pixmap->refCount<1) {
|
||||
XFreePixmap(pixmap->screen->display, pixmap->pixmap);
|
||||
if (pixmap->mask)
|
||||
XFreePixmap(pixmap->screen->display, pixmap->mask);
|
||||
free(pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMPixmap*
|
||||
WMCreatePixmapFromXPixmaps(WMScreen *scrPtr, Pixmap pixmap, Pixmap mask,
|
||||
int width, int height, int depth)
|
||||
{
|
||||
WMPixmap *pixPtr;
|
||||
|
||||
pixPtr = malloc(sizeof(WMPixmap));
|
||||
if (!pixPtr) {
|
||||
return NULL;
|
||||
}
|
||||
pixPtr->screen = scrPtr;
|
||||
pixPtr->pixmap = pixmap;
|
||||
pixPtr->mask = mask;
|
||||
pixPtr->width = width;
|
||||
pixPtr->height = height;
|
||||
pixPtr->depth = depth;
|
||||
pixPtr->refCount = 1;
|
||||
|
||||
return pixPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
WMPixmap*
|
||||
WMCreatePixmapFromFile(WMScreen *scrPtr, char *fileName)
|
||||
{
|
||||
WMPixmap *pixPtr;
|
||||
RImage *image;
|
||||
|
||||
image = RLoadImage(scrPtr->rcontext, fileName, 0);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
pixPtr = WMCreatePixmapFromRImage(scrPtr, image, 127);
|
||||
|
||||
RDestroyImage(image);
|
||||
|
||||
return pixPtr;
|
||||
}
|
||||
|
||||
|
||||
WMPixmap*
|
||||
WMCreatePixmapFromRImage(WMScreen *scrPtr, RImage *image, int threshold)
|
||||
{
|
||||
WMPixmap *pixPtr;
|
||||
Pixmap pixmap, mask;
|
||||
|
||||
if (!RConvertImageMask(scrPtr->rcontext, image, &pixmap, &mask,
|
||||
threshold)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pixPtr = malloc(sizeof(WMPixmap));
|
||||
if (!pixPtr) {
|
||||
return NULL;
|
||||
}
|
||||
pixPtr->screen = scrPtr;
|
||||
pixPtr->pixmap = pixmap;
|
||||
pixPtr->mask = mask;
|
||||
pixPtr->width = image->width;
|
||||
pixPtr->height = image->height;
|
||||
pixPtr->depth = scrPtr->depth;
|
||||
pixPtr->refCount = 1;
|
||||
|
||||
return pixPtr;
|
||||
}
|
||||
|
||||
|
||||
WMPixmap*
|
||||
WMCreateBlendedPixmapFromFile(WMScreen *scrPtr, char *fileName, RColor *color)
|
||||
{
|
||||
WMPixmap *pixPtr;
|
||||
RImage *image;
|
||||
|
||||
|
||||
image = RLoadImage(scrPtr->rcontext, fileName, 0);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
RCombineImageWithColor(image, color);
|
||||
|
||||
pixPtr = WMCreatePixmapFromRImage(scrPtr, image, 0);
|
||||
|
||||
RDestroyImage(image);
|
||||
|
||||
return pixPtr;
|
||||
}
|
||||
|
||||
|
||||
WMPixmap*
|
||||
WMCreatePixmapFromXPMData(WMScreen *scrPtr, char **data)
|
||||
{
|
||||
WMPixmap *pixPtr;
|
||||
RImage *image;
|
||||
|
||||
image = RGetImageFromXPMData(scrPtr->rcontext, data);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
pixPtr = WMCreatePixmapFromRImage(scrPtr, image, 127);
|
||||
|
||||
RDestroyImage(image);
|
||||
|
||||
return pixPtr;
|
||||
}
|
||||
|
||||
|
||||
Pixmap
|
||||
WMGetPixmapXID(WMPixmap *pixmap)
|
||||
{
|
||||
return pixmap->pixmap;
|
||||
}
|
||||
|
||||
Pixmap
|
||||
WMGetPixmapMaskXID(WMPixmap *pixmap)
|
||||
{
|
||||
return pixmap->mask;
|
||||
}
|
||||
|
||||
|
||||
WMSize
|
||||
WMGetPixmapSize(WMPixmap *pixmap)
|
||||
{
|
||||
WMSize size;
|
||||
|
||||
size.width = pixmap->width;
|
||||
size.height = pixmap->height;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
WMPixmap*
|
||||
WMGetSystemPixmap(WMScreen *scr, int image)
|
||||
{
|
||||
switch (image) {
|
||||
case WSIReturnArrow:
|
||||
return WMRetainPixmap(scr->buttonArrow);
|
||||
|
||||
case WSIHighlightedReturnArrow:
|
||||
return WMRetainPixmap(scr->pushedButtonArrow);
|
||||
|
||||
case WSIScrollerDimple:
|
||||
return WMRetainPixmap(scr->scrollerDimple);
|
||||
|
||||
case WSIArrowLeft:
|
||||
return WMRetainPixmap(scr->leftArrow);
|
||||
|
||||
case WSIHighlightedArrowLeft:
|
||||
return WMRetainPixmap(scr->hiLeftArrow);
|
||||
|
||||
case WSIArrowRight:
|
||||
return WMRetainPixmap(scr->rightArrow);
|
||||
|
||||
case WSIHighlightedArrowRight:
|
||||
return WMRetainPixmap(scr->hiRightArrow);
|
||||
|
||||
case WSIArrowUp:
|
||||
return WMRetainPixmap(scr->upArrow);
|
||||
|
||||
case WSIHighlightedArrowUp:
|
||||
return WMRetainPixmap(scr->hiUpArrow);
|
||||
|
||||
case WSIArrowDown:
|
||||
return WMRetainPixmap(scr->downArrow);
|
||||
|
||||
case WSIHighlightedArrowDown:
|
||||
return WMRetainPixmap(scr->hiDownArrow);
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
709
WINGs/wpopupbutton.c
Normal file
709
WINGs/wpopupbutton.c
Normal file
@@ -0,0 +1,709 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
typedef struct ItemList {
|
||||
char *text;
|
||||
struct ItemList *nextPtr;
|
||||
unsigned int disabled:1;
|
||||
} ItemList;
|
||||
|
||||
typedef struct W_PopUpButton {
|
||||
W_Class widgetClass;
|
||||
WMView *view;
|
||||
|
||||
void *clientData;
|
||||
WMAction *action;
|
||||
|
||||
char *caption;
|
||||
|
||||
ItemList *items;
|
||||
short itemCount;
|
||||
|
||||
short selectedItemIndex;
|
||||
|
||||
short highlightedItem;
|
||||
|
||||
ItemList *selectedItem; /* selected item if it is a menu btn */
|
||||
|
||||
WMView *menuView; /* override redirect popup menu */
|
||||
|
||||
struct {
|
||||
unsigned int pullsDown:1;
|
||||
|
||||
unsigned int configured:1;
|
||||
|
||||
unsigned int insideMenu:1;
|
||||
} flags;
|
||||
} PopUpButton;
|
||||
|
||||
|
||||
#define MENU_BLINK_DELAY 60000
|
||||
#define MENU_BLINK_COUNT 2
|
||||
|
||||
|
||||
W_ViewProcedureTable _PopUpButtonViewProcedures = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#define DEFAULT_WIDTH 60
|
||||
#define DEFAULT_HEIGHT 20
|
||||
#define DEFAULT_CAPTION ""
|
||||
|
||||
|
||||
static void destroyPopUpButton(PopUpButton *bPtr);
|
||||
static void paintPopUpButton(PopUpButton *bPtr);
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleActionEvents(XEvent *event, void *data);
|
||||
|
||||
static void resizeMenu(PopUpButton *bPtr);
|
||||
|
||||
|
||||
WMPopUpButton*
|
||||
WMCreatePopUpButton(WMWidget *parent)
|
||||
{
|
||||
PopUpButton *bPtr;
|
||||
W_Screen *scr = W_VIEW(parent)->screen;
|
||||
|
||||
|
||||
bPtr = wmalloc(sizeof(PopUpButton));
|
||||
memset(bPtr, 0, sizeof(PopUpButton));
|
||||
|
||||
bPtr->widgetClass = WC_PopUpButton;
|
||||
|
||||
bPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!bPtr->view) {
|
||||
free(bPtr);
|
||||
return NULL;
|
||||
}
|
||||
bPtr->view->self = bPtr;
|
||||
|
||||
WMCreateEventHandler(bPtr->view, ExposureMask|StructureNotifyMask
|
||||
|ClientMessageMask, handleEvents, bPtr);
|
||||
|
||||
|
||||
W_ResizeView(bPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
bPtr->caption = wstrdup(DEFAULT_CAPTION);
|
||||
|
||||
WMCreateEventHandler(bPtr->view, ButtonPressMask|ButtonReleaseMask,
|
||||
handleActionEvents, bPtr);
|
||||
|
||||
bPtr->menuView = W_CreateTopView(scr);
|
||||
bPtr->menuView->attribs.override_redirect = True;
|
||||
bPtr->menuView->attribFlags |= CWOverrideRedirect;
|
||||
|
||||
W_ResizeView(bPtr->menuView, bPtr->view->size.width, 1);
|
||||
|
||||
WMCreateEventHandler(bPtr->menuView, ButtonPressMask|ButtonReleaseMask
|
||||
|EnterWindowMask|LeaveWindowMask|ButtonMotionMask,
|
||||
handleActionEvents, bPtr);
|
||||
|
||||
return bPtr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetPopUpButtonAction(WMPopUpButton *bPtr, WMAction *action, void *clientData)
|
||||
{
|
||||
CHECK_CLASS(bPtr, WC_PopUpButton);
|
||||
|
||||
bPtr->action = action;
|
||||
|
||||
bPtr->clientData = clientData;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMAddPopUpButtonItem(WMPopUpButton *bPtr, char *title)
|
||||
{
|
||||
ItemList *itemPtr, *tmp;
|
||||
|
||||
CHECK_CLASS(bPtr, WC_PopUpButton);
|
||||
|
||||
itemPtr = wmalloc(sizeof(ItemList));
|
||||
memset(itemPtr, 0, sizeof(ItemList));
|
||||
itemPtr->text = wstrdup(title);
|
||||
|
||||
/* append item to list */
|
||||
tmp = bPtr->items;
|
||||
if (!tmp)
|
||||
bPtr->items = itemPtr;
|
||||
else {
|
||||
while (tmp->nextPtr!=NULL)
|
||||
tmp = tmp->nextPtr;
|
||||
tmp->nextPtr = itemPtr;
|
||||
}
|
||||
|
||||
bPtr->itemCount++;
|
||||
|
||||
if (bPtr->menuView && bPtr->menuView->flags.realized)
|
||||
resizeMenu(bPtr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMInsertPopUpButtonItem(WMPopUpButton *bPtr, int index, char *title)
|
||||
{
|
||||
ItemList *itemPtr;
|
||||
|
||||
CHECK_CLASS(bPtr, WC_PopUpButton);
|
||||
|
||||
if (index < 0)
|
||||
index = 0;
|
||||
if (index >= bPtr->itemCount) {
|
||||
WMAddPopUpButtonItem(bPtr, title);
|
||||
return;
|
||||
}
|
||||
|
||||
itemPtr = wmalloc(sizeof(ItemList));
|
||||
memset(itemPtr, 0, sizeof(ItemList));
|
||||
itemPtr->text = wstrdup(title);
|
||||
|
||||
if (index == 0) {
|
||||
itemPtr->nextPtr = bPtr->items;
|
||||
bPtr->items = itemPtr;
|
||||
} else {
|
||||
ItemList *tmp;
|
||||
int i = index;
|
||||
|
||||
tmp = bPtr->items;
|
||||
/* insert item in list */
|
||||
while (--i > 0) {
|
||||
tmp = tmp->nextPtr;
|
||||
}
|
||||
bPtr->items->nextPtr = tmp->nextPtr;
|
||||
tmp->nextPtr = bPtr->items;
|
||||
}
|
||||
|
||||
bPtr->itemCount++;
|
||||
|
||||
/* if there is an selected item, update it's index to match the new
|
||||
* position */
|
||||
if (index < bPtr->selectedItemIndex)
|
||||
bPtr->selectedItemIndex++;
|
||||
|
||||
if (bPtr->menuView && bPtr->menuView->flags.realized)
|
||||
resizeMenu(bPtr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMRemovePopUpButtonItem(WMPopUpButton *bPtr, int index)
|
||||
{
|
||||
ItemList *tmp;
|
||||
|
||||
CHECK_CLASS(bPtr, WC_PopUpButton);
|
||||
|
||||
if (index < 0 || index >= bPtr->itemCount)
|
||||
return;
|
||||
|
||||
|
||||
if (index == 0) {
|
||||
free(bPtr->items->text);
|
||||
tmp = bPtr->items->nextPtr;
|
||||
free(bPtr->items);
|
||||
bPtr->items = tmp;
|
||||
} else {
|
||||
ItemList *next;
|
||||
int i = index;
|
||||
|
||||
tmp = bPtr->items;
|
||||
while (--i > 0)
|
||||
tmp = tmp->nextPtr;
|
||||
next = tmp->nextPtr->nextPtr;
|
||||
|
||||
free(tmp->nextPtr->text);
|
||||
free(tmp->nextPtr);
|
||||
|
||||
tmp->nextPtr = next;
|
||||
}
|
||||
|
||||
bPtr->itemCount--;
|
||||
|
||||
if (bPtr->selectedItem!=NULL && !bPtr->flags.pullsDown) {
|
||||
if (index < bPtr->selectedItemIndex)
|
||||
bPtr->selectedItemIndex--;
|
||||
else if (index == bPtr->selectedItemIndex) {
|
||||
/* reselect first item if the removed item is the
|
||||
* selected one */
|
||||
bPtr->selectedItem = bPtr->items;
|
||||
bPtr->selectedItemIndex = 0;
|
||||
if (bPtr->view->flags.mapped)
|
||||
paintPopUpButton(bPtr);
|
||||
}
|
||||
}
|
||||
|
||||
if (bPtr->menuView && bPtr->menuView->flags.realized)
|
||||
resizeMenu(bPtr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetPopUpButtonSelectedItem(WMPopUpButton *bPtr, int index)
|
||||
{
|
||||
ItemList *itemPtr = bPtr->items;
|
||||
int i = index;
|
||||
|
||||
if (index < 0) {
|
||||
bPtr->selectedItem = NULL;
|
||||
if (bPtr->view->flags.mapped)
|
||||
paintPopUpButton(bPtr);
|
||||
return;
|
||||
}
|
||||
|
||||
while (i-- > 0) {
|
||||
itemPtr = itemPtr->nextPtr;
|
||||
}
|
||||
bPtr->selectedItem = itemPtr;
|
||||
bPtr->selectedItemIndex = index;
|
||||
|
||||
if (bPtr->view->flags.mapped)
|
||||
paintPopUpButton(bPtr);
|
||||
}
|
||||
|
||||
int
|
||||
WMGetPopUpButtonSelectedItem(WMPopUpButton *bPtr)
|
||||
{
|
||||
if (!bPtr->flags.pullsDown && bPtr->selectedItem==NULL)
|
||||
return -1;
|
||||
else
|
||||
return bPtr->selectedItemIndex;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetPopUpButtonText(WMPopUpButton *bPtr, char *text)
|
||||
{
|
||||
if (bPtr->caption)
|
||||
free(bPtr->caption);
|
||||
if (text)
|
||||
bPtr->caption = wstrdup(text);
|
||||
else
|
||||
bPtr->caption = NULL;
|
||||
if (bPtr->view->flags.realized) {
|
||||
if (bPtr->flags.pullsDown || bPtr->selectedItemIndex < 0) {
|
||||
paintPopUpButton(bPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetPopUpButtonItemEnabled(WMPopUpButton *bPtr, int index, Bool flag)
|
||||
{
|
||||
int i;
|
||||
ItemList *item = bPtr->items;
|
||||
|
||||
if (index < 0 || index >= bPtr->itemCount)
|
||||
return;
|
||||
|
||||
for (i = 0; i<index; i++)
|
||||
item=item->nextPtr;
|
||||
|
||||
item->disabled = !flag;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetPopUpButtonPullsDown(WMPopUpButton *bPtr, Bool flag)
|
||||
{
|
||||
bPtr->flags.pullsDown = flag;
|
||||
if (!flag) {
|
||||
bPtr->selectedItem = bPtr->items;
|
||||
if (bPtr->selectedItem)
|
||||
bPtr->selectedItemIndex = 0;
|
||||
else
|
||||
bPtr->selectedItemIndex = -1;
|
||||
} else
|
||||
bPtr->selectedItemIndex = -1;
|
||||
|
||||
if (bPtr->view->flags.mapped)
|
||||
paintPopUpButton(bPtr);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetPopUpButtonNumberOfItems(WMPopUpButton *bPtr)
|
||||
{
|
||||
return bPtr->itemCount;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMGetPopUpButtonItem(WMPopUpButton *bPtr, int index)
|
||||
{
|
||||
ItemList *itemPtr = bPtr->items;
|
||||
|
||||
if ((index < 0) || (index >= bPtr->itemCount))
|
||||
return NULL;
|
||||
|
||||
while (index-->0)
|
||||
itemPtr = itemPtr->nextPtr;
|
||||
|
||||
return itemPtr->text;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintPopUpButton(PopUpButton *bPtr)
|
||||
{
|
||||
W_Screen *scr = bPtr->view->screen;
|
||||
char *caption;
|
||||
Pixmap pixmap;
|
||||
|
||||
|
||||
if (bPtr->flags.pullsDown) {
|
||||
caption = bPtr->caption;
|
||||
} else {
|
||||
if (bPtr->selectedItem == NULL) {
|
||||
/* if no item selected, show the caption */
|
||||
caption = bPtr->caption;
|
||||
} else {
|
||||
caption = bPtr->selectedItem->text;
|
||||
}
|
||||
}
|
||||
|
||||
pixmap = XCreatePixmap(scr->display, bPtr->view->window,
|
||||
bPtr->view->size.width, bPtr->view->size.height,
|
||||
scr->depth);
|
||||
XFillRectangle(scr->display, pixmap, W_GC(scr->gray), 0, 0,
|
||||
bPtr->view->size.width, bPtr->view->size.height);
|
||||
|
||||
W_DrawRelief(scr, pixmap, 0, 0, bPtr->view->size.width,
|
||||
bPtr->view->size.height, WRRaised);
|
||||
|
||||
if (caption) {
|
||||
W_PaintText(bPtr->view, pixmap, scr->normalFont,
|
||||
6, (bPtr->view->size.height-scr->normalFont->height)/2,
|
||||
bPtr->view->size.width, WALeft, W_GC(scr->black), False,
|
||||
caption, strlen(caption));
|
||||
}
|
||||
|
||||
if (bPtr->flags.pullsDown) {
|
||||
XCopyArea(scr->display, scr->pullDownIndicator->pixmap,
|
||||
pixmap, scr->copyGC, 0, 0, scr->pullDownIndicator->width,
|
||||
scr->pullDownIndicator->height,
|
||||
bPtr->view->size.width-scr->pullDownIndicator->width-4,
|
||||
(bPtr->view->size.height-scr->pullDownIndicator->height)/2);
|
||||
} else {
|
||||
int x, y;
|
||||
|
||||
x = bPtr->view->size.width - scr->popUpIndicator->width - 4;
|
||||
y = (bPtr->view->size.height-scr->popUpIndicator->height)/2;
|
||||
|
||||
XSetClipOrigin(scr->display, scr->clipGC, x, y);
|
||||
XSetClipMask(scr->display, scr->clipGC, scr->popUpIndicator->mask);
|
||||
XCopyArea(scr->display, scr->popUpIndicator->pixmap, pixmap,
|
||||
scr->clipGC, 0, 0, scr->popUpIndicator->width,
|
||||
scr->popUpIndicator->height, x, y);
|
||||
}
|
||||
|
||||
XCopyArea(scr->display, pixmap, bPtr->view->window, scr->copyGC, 0, 0,
|
||||
bPtr->view->size.width, bPtr->view->size.height, 0, 0);
|
||||
|
||||
XFreePixmap(scr->display, pixmap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
PopUpButton *bPtr = (PopUpButton*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_PopUpButton);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintPopUpButton(bPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyPopUpButton(bPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
paintMenuEntry(PopUpButton *bPtr, int index, int highlight)
|
||||
{
|
||||
W_Screen *scr = bPtr->view->screen;
|
||||
int i;
|
||||
int yo;
|
||||
ItemList *itemPtr;
|
||||
int width, height, itemHeight;
|
||||
|
||||
itemHeight = bPtr->view->size.height;
|
||||
width = bPtr->view->size.width;
|
||||
height = itemHeight * bPtr->itemCount;
|
||||
yo = (itemHeight - scr->normalFont->height)/2;
|
||||
|
||||
if (!highlight) {
|
||||
XClearArea(scr->display, bPtr->menuView->window, 0, index*itemHeight,
|
||||
width, itemHeight, False);
|
||||
return;
|
||||
} else if (index < 0 && bPtr->flags.pullsDown) {
|
||||
return;
|
||||
}
|
||||
|
||||
XFillRectangle(scr->display, bPtr->menuView->window, W_GC(scr->white),
|
||||
1, index*itemHeight+1, width-3, itemHeight-3);
|
||||
|
||||
itemPtr = bPtr->items;
|
||||
for (i = 0; i < index; i++)
|
||||
itemPtr = itemPtr->nextPtr;
|
||||
|
||||
W_DrawRelief(scr, bPtr->menuView->window, 0, index*itemHeight,
|
||||
width, itemHeight, WRRaised);
|
||||
|
||||
W_PaintText(bPtr->menuView, bPtr->menuView->window, scr->normalFont, 6,
|
||||
index*itemHeight + yo, width, WALeft, W_GC(scr->black), False,
|
||||
itemPtr->text, strlen(itemPtr->text));
|
||||
|
||||
if (!bPtr->flags.pullsDown && index == bPtr->selectedItemIndex) {
|
||||
XCopyArea(scr->display, scr->popUpIndicator->pixmap,
|
||||
bPtr->menuView->window, scr->copyGC, 0, 0,
|
||||
scr->popUpIndicator->width, scr->popUpIndicator->height,
|
||||
width-scr->popUpIndicator->width-4,
|
||||
i*itemHeight+(itemHeight-scr->popUpIndicator->height)/2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Pixmap
|
||||
makeMenuPixmap(PopUpButton *bPtr)
|
||||
{
|
||||
Pixmap pixmap;
|
||||
W_Screen *scr = bPtr->view->screen;
|
||||
int i;
|
||||
int yo;
|
||||
ItemList *itemPtr;
|
||||
int width, height, itemHeight;
|
||||
|
||||
itemHeight = bPtr->view->size.height;
|
||||
width = bPtr->view->size.width;
|
||||
height = itemHeight * bPtr->itemCount;
|
||||
yo = (itemHeight - scr->normalFont->height)/2;
|
||||
|
||||
pixmap = XCreatePixmap(scr->display, bPtr->view->window, width, height,
|
||||
scr->depth);
|
||||
|
||||
XFillRectangle(scr->display, pixmap, W_GC(scr->gray), 0, 0, width, height);
|
||||
|
||||
itemPtr = bPtr->items;
|
||||
for (i = 0; i < bPtr->itemCount; i++) {
|
||||
GC gc;
|
||||
|
||||
W_DrawRelief(scr, pixmap, 0, i*itemHeight, width, itemHeight,
|
||||
WRRaised);
|
||||
|
||||
if (itemPtr->disabled)
|
||||
gc = W_GC(scr->darkGray);
|
||||
else
|
||||
gc = W_GC(scr->black);
|
||||
|
||||
W_PaintText(bPtr->menuView, pixmap, scr->normalFont, 6,
|
||||
i*itemHeight + yo, width, WALeft, gc, False,
|
||||
itemPtr->text, strlen(itemPtr->text));
|
||||
|
||||
if (!bPtr->flags.pullsDown && i == bPtr->selectedItemIndex) {
|
||||
XCopyArea(scr->display, scr->popUpIndicator->pixmap, pixmap,
|
||||
scr->copyGC, 0, 0, scr->popUpIndicator->width,
|
||||
scr->popUpIndicator->height,
|
||||
width-scr->popUpIndicator->width-4,
|
||||
i*itemHeight+(itemHeight-scr->popUpIndicator->height)/2);
|
||||
}
|
||||
itemPtr = itemPtr->nextPtr;
|
||||
}
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resizeMenu(PopUpButton *bPtr)
|
||||
{
|
||||
int height;
|
||||
|
||||
height = bPtr->itemCount * bPtr->view->size.height;
|
||||
W_ResizeView(bPtr->menuView, bPtr->view->size.width, height);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
popUpMenu(PopUpButton *bPtr)
|
||||
{
|
||||
W_Screen *scr = bPtr->view->screen;
|
||||
Window dummyW;
|
||||
int x, y;
|
||||
|
||||
if (!bPtr->menuView->flags.realized) {
|
||||
W_RealizeView(bPtr->menuView);
|
||||
resizeMenu(bPtr);
|
||||
}
|
||||
|
||||
if (bPtr->itemCount < 1)
|
||||
return;
|
||||
|
||||
XTranslateCoordinates(scr->display, bPtr->view->window, scr->rootWin,
|
||||
0, 0, &x, &y, &dummyW);
|
||||
|
||||
if (bPtr->flags.pullsDown) {
|
||||
y += bPtr->view->size.height;
|
||||
} else {
|
||||
y -= bPtr->view->size.height*bPtr->selectedItemIndex;
|
||||
}
|
||||
W_MoveView(bPtr->menuView, x, y);
|
||||
|
||||
XSetWindowBackgroundPixmap(scr->display, bPtr->menuView->window,
|
||||
makeMenuPixmap(bPtr));
|
||||
XClearWindow(scr->display, bPtr->menuView->window);
|
||||
|
||||
W_MapView(bPtr->menuView);
|
||||
|
||||
bPtr->highlightedItem = 0;
|
||||
if (!bPtr->flags.pullsDown && bPtr->selectedItem != NULL)
|
||||
paintMenuEntry(bPtr, bPtr->selectedItemIndex, True);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
popDownMenu(PopUpButton *bPtr)
|
||||
{
|
||||
W_UnmapView(bPtr->menuView);
|
||||
|
||||
/* free the background pixmap used to draw the menu contents */
|
||||
XSetWindowBackgroundPixmap(bPtr->view->screen->display,
|
||||
bPtr->menuView->window, None);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
itemIsEnabled(PopUpButton *bPtr, int index)
|
||||
{
|
||||
ItemList *item = bPtr->items;
|
||||
|
||||
while (index-- > 0)
|
||||
item = item->nextPtr;
|
||||
|
||||
return !item->disabled;
|
||||
}
|
||||
|
||||
static void
|
||||
handleActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
PopUpButton *bPtr = (PopUpButton*)data;
|
||||
int oldItem;
|
||||
|
||||
CHECK_CLASS(data, WC_PopUpButton);
|
||||
|
||||
if (bPtr->itemCount < 1)
|
||||
return;
|
||||
|
||||
switch (event->type) {
|
||||
/* called for menuView */
|
||||
case LeaveNotify:
|
||||
bPtr->flags.insideMenu = 0;
|
||||
if (bPtr->menuView->flags.mapped)
|
||||
paintMenuEntry(bPtr, bPtr->highlightedItem, False);
|
||||
bPtr->highlightedItem = -1;
|
||||
break;
|
||||
|
||||
case EnterNotify:
|
||||
bPtr->flags.insideMenu = 1;
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
if (bPtr->flags.insideMenu) {
|
||||
oldItem = bPtr->highlightedItem;
|
||||
bPtr->highlightedItem = event->xmotion.y / bPtr->view->size.height;
|
||||
if (oldItem!=bPtr->highlightedItem) {
|
||||
paintMenuEntry(bPtr, oldItem, False);
|
||||
paintMenuEntry(bPtr, bPtr->highlightedItem,
|
||||
itemIsEnabled(bPtr, bPtr->highlightedItem));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* called for bPtr->view */
|
||||
case ButtonPress:
|
||||
popUpMenu(bPtr);
|
||||
if (!bPtr->flags.pullsDown) {
|
||||
bPtr->highlightedItem = bPtr->selectedItemIndex;
|
||||
bPtr->flags.insideMenu = 1;
|
||||
} else {
|
||||
bPtr->highlightedItem = -1;
|
||||
bPtr->flags.insideMenu = 0;
|
||||
}
|
||||
XGrabPointer(bPtr->view->screen->display, bPtr->menuView->window,
|
||||
False, ButtonReleaseMask|ButtonMotionMask|EnterWindowMask
|
||||
|LeaveWindowMask, GrabModeAsync, GrabModeAsync,
|
||||
None, None, CurrentTime);
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
XUngrabPointer(bPtr->view->screen->display, event->xbutton.time);
|
||||
if (!bPtr->flags.pullsDown)
|
||||
popDownMenu(bPtr);
|
||||
if (bPtr->flags.insideMenu && bPtr->highlightedItem>=0) {
|
||||
if (itemIsEnabled(bPtr, bPtr->highlightedItem)) {
|
||||
int i;
|
||||
WMSetPopUpButtonSelectedItem(bPtr, bPtr->highlightedItem);
|
||||
|
||||
if (bPtr->flags.pullsDown) {
|
||||
for (i=0; i<MENU_BLINK_COUNT; i++) {
|
||||
paintMenuEntry(bPtr, bPtr->highlightedItem, False);
|
||||
XSync(bPtr->view->screen->display, 0);
|
||||
wusleep(MENU_BLINK_DELAY);
|
||||
paintMenuEntry(bPtr, bPtr->highlightedItem, True);
|
||||
XSync(bPtr->view->screen->display, 0);
|
||||
wusleep(MENU_BLINK_DELAY);
|
||||
}
|
||||
}
|
||||
paintMenuEntry(bPtr, bPtr->highlightedItem, False);
|
||||
popDownMenu(bPtr);
|
||||
if (bPtr->action)
|
||||
(*bPtr->action)(bPtr, bPtr->clientData);
|
||||
}
|
||||
}
|
||||
if (bPtr->menuView->flags.mapped)
|
||||
popDownMenu(bPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroyPopUpButton(PopUpButton *bPtr)
|
||||
{
|
||||
ItemList *itemPtr, *tmp;
|
||||
|
||||
itemPtr = bPtr->items;
|
||||
while (itemPtr!=NULL) {
|
||||
free(itemPtr->text);
|
||||
tmp = itemPtr->nextPtr;
|
||||
free(itemPtr);
|
||||
itemPtr = tmp;
|
||||
}
|
||||
|
||||
if (bPtr->caption)
|
||||
free(bPtr->caption);
|
||||
|
||||
/* have to destroy explicitly because the popup is a toplevel */
|
||||
W_DestroyView(bPtr->menuView);
|
||||
|
||||
free(bPtr);
|
||||
}
|
||||
863
WINGs/wscroller.c
Normal file
863
WINGs/wscroller.c
Normal file
@@ -0,0 +1,863 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
/* undefine will disable the autoadjusting of the knob dimple to be
|
||||
* directly below the cursor
|
||||
* DOES NOT WORK */
|
||||
#undef STRICT_NEXT_BEHAVIOUR
|
||||
|
||||
#define AUTOSCROLL_INITIAL_DELAY 200
|
||||
|
||||
#define AUTOSCROLL_DELAY 40
|
||||
|
||||
|
||||
typedef struct W_Scroller {
|
||||
W_Class widgetClass;
|
||||
W_View *view;
|
||||
|
||||
void *clientData;
|
||||
WMAction *action;
|
||||
|
||||
float knobProportion;
|
||||
float floatValue;
|
||||
|
||||
WMHandlerID timerID; /* for continuous scrolling mode */
|
||||
|
||||
#ifndef STRICT_NEXT_BEHAVIOUR
|
||||
int dragPoint; /* point where the knob is being
|
||||
* dragged */
|
||||
#endif
|
||||
struct {
|
||||
WMScrollArrowPosition arrowsPosition:3;
|
||||
|
||||
unsigned int horizontal:1;
|
||||
|
||||
WMScrollerPart hitPart:3;
|
||||
|
||||
/* */
|
||||
unsigned int documentFullyVisible:1; /* document is fully visible */
|
||||
|
||||
unsigned int prevSelected:1;
|
||||
|
||||
unsigned int pushed:1;
|
||||
|
||||
unsigned int incrDown:1; /* whether increment button is down */
|
||||
|
||||
unsigned int decrDown:1;
|
||||
|
||||
unsigned int draggingKnob:1;
|
||||
|
||||
unsigned int configured:1;
|
||||
|
||||
unsigned int redrawPending:1;
|
||||
} flags;
|
||||
} Scroller;
|
||||
|
||||
|
||||
|
||||
#define DEFAULT_HEIGHT 60
|
||||
#define DEFAULT_WIDTH SCROLLER_WIDTH
|
||||
#define DEFAULT_ARROWS_POSITION WSAMinEnd
|
||||
|
||||
|
||||
|
||||
static void destroyScroller(Scroller *sPtr);
|
||||
static void paintScroller(Scroller *sPtr);
|
||||
|
||||
static void resizeScroller();
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleActionEvents(XEvent *event, void *data);
|
||||
|
||||
static void handleMotion(Scroller *sPtr, int mouseX, int mouseY);
|
||||
|
||||
|
||||
W_ViewProcedureTable _ScrollerViewProcedures = {
|
||||
NULL,
|
||||
resizeScroller,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
WMScroller*
|
||||
WMCreateScroller(WMWidget *parent)
|
||||
{
|
||||
Scroller *sPtr;
|
||||
|
||||
sPtr = wmalloc(sizeof(Scroller));
|
||||
memset(sPtr, 0, sizeof(Scroller));
|
||||
|
||||
sPtr->widgetClass = WC_Scroller;
|
||||
|
||||
sPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!sPtr->view) {
|
||||
free(sPtr);
|
||||
return NULL;
|
||||
}
|
||||
sPtr->view->self = sPtr;
|
||||
|
||||
sPtr->flags.documentFullyVisible = 1;
|
||||
|
||||
WMCreateEventHandler(sPtr->view, ExposureMask|StructureNotifyMask
|
||||
|ClientMessageMask, handleEvents, sPtr);
|
||||
|
||||
resizeScroller(sPtr, DEFAULT_WIDTH, DEFAULT_WIDTH);
|
||||
sPtr->flags.arrowsPosition = DEFAULT_ARROWS_POSITION;
|
||||
|
||||
WMCreateEventHandler(sPtr->view, ButtonPressMask|ButtonReleaseMask
|
||||
|EnterWindowMask|LeaveWindowMask|ButtonMotionMask,
|
||||
handleActionEvents, sPtr);
|
||||
|
||||
sPtr->flags.hitPart = WSNoPart;
|
||||
|
||||
return sPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetScrollerArrowsPosition(WMScroller *sPtr, WMScrollArrowPosition position)
|
||||
{
|
||||
sPtr->flags.arrowsPosition = position;
|
||||
if (sPtr->view->flags.realized) {
|
||||
paintScroller(sPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resizeScroller(WMScroller *sPtr, unsigned int width, unsigned int height)
|
||||
{
|
||||
if (width > height) {
|
||||
sPtr->flags.horizontal = 1;
|
||||
W_ResizeView(sPtr->view, width, SCROLLER_WIDTH);
|
||||
} else {
|
||||
sPtr->flags.horizontal = 0;
|
||||
W_ResizeView(sPtr->view, SCROLLER_WIDTH, height);
|
||||
}
|
||||
if (sPtr->view->flags.realized) {
|
||||
paintScroller(sPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetScrollerAction(WMScroller *sPtr, WMAction *action, void *clientData)
|
||||
{
|
||||
CHECK_CLASS(sPtr, WC_Scroller);
|
||||
|
||||
sPtr->action = action;
|
||||
|
||||
sPtr->clientData = clientData;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetScrollerParameters(WMScroller *sPtr, float floatValue,
|
||||
float knobProportion)
|
||||
{
|
||||
CHECK_CLASS(sPtr, WC_Scroller);
|
||||
|
||||
if (floatValue < 0.0)
|
||||
sPtr->floatValue = 0.0;
|
||||
else if (floatValue > 1.0)
|
||||
sPtr->floatValue = 1.0;
|
||||
else
|
||||
sPtr->floatValue = floatValue;
|
||||
|
||||
if (knobProportion <= 0.0) {
|
||||
|
||||
sPtr->knobProportion = 0.0;
|
||||
sPtr->flags.documentFullyVisible = 0;
|
||||
|
||||
} else if (knobProportion >= 1.0) {
|
||||
|
||||
sPtr->knobProportion = 1.0;
|
||||
sPtr->flags.documentFullyVisible = 1;
|
||||
|
||||
} else {
|
||||
sPtr->knobProportion = knobProportion;
|
||||
sPtr->flags.documentFullyVisible = 0;
|
||||
}
|
||||
|
||||
if (sPtr->view->flags.realized)
|
||||
paintScroller(sPtr);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
WMGetScrollerKnobProportion(WMScroller *sPtr)
|
||||
{
|
||||
CHECK_CLASS(sPtr, WC_Scroller);
|
||||
|
||||
return sPtr->knobProportion;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
WMGetScrollerValue(WMScroller *sPtr)
|
||||
{
|
||||
CHECK_CLASS(sPtr, WC_Scroller);
|
||||
|
||||
return sPtr->floatValue;
|
||||
}
|
||||
|
||||
|
||||
WMScrollerPart
|
||||
WMGetScrollerHitPart(WMScroller *sPtr)
|
||||
{
|
||||
CHECK_CLASS(sPtr, WC_Scroller);
|
||||
|
||||
return sPtr->flags.hitPart;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintArrow(WMScroller *sPtr, Drawable d, int part)
|
||||
/*
|
||||
* part- 0 paints the decrement arrow, 1 the increment arrow
|
||||
*/
|
||||
{
|
||||
WMView *view = sPtr->view;
|
||||
WMScreen *scr = view->screen;
|
||||
int ofs, bsize;
|
||||
W_Pixmap *arrow;
|
||||
|
||||
#ifndef DOUBLE_BUFFER
|
||||
GC gc = scr->lightGC;
|
||||
#endif
|
||||
|
||||
bsize = SCROLLER_WIDTH - 4;
|
||||
|
||||
|
||||
if (part == 0) { /* decrement button */
|
||||
if (sPtr->flags.horizontal) {
|
||||
if (sPtr->flags.arrowsPosition == WSAMaxEnd) {
|
||||
ofs = view->size.width - 2*(bsize+1) - 1;
|
||||
} else {
|
||||
ofs = 2;
|
||||
}
|
||||
if (sPtr->flags.decrDown)
|
||||
arrow = scr->hiLeftArrow;
|
||||
else
|
||||
arrow = scr->leftArrow;
|
||||
|
||||
} else {
|
||||
if (sPtr->flags.arrowsPosition == WSAMaxEnd) {
|
||||
ofs = view->size.height - 2*(bsize+1) - 1;
|
||||
} else {
|
||||
ofs = 2;
|
||||
}
|
||||
if (sPtr->flags.decrDown)
|
||||
arrow = scr->hiUpArrow;
|
||||
else
|
||||
arrow = scr->upArrow;
|
||||
}
|
||||
|
||||
#ifndef DOUBLE_BUFFER
|
||||
if (sPtr->flags.decrDown)
|
||||
gc = W_GC(scr->white);
|
||||
#endif
|
||||
} else { /* increment button */
|
||||
if (sPtr->flags.horizontal) {
|
||||
if (sPtr->flags.arrowsPosition == WSAMaxEnd) {
|
||||
ofs = view->size.width - bsize+1 - 3;
|
||||
} else {
|
||||
ofs = 2 + bsize+1;
|
||||
}
|
||||
if (sPtr->flags.incrDown)
|
||||
arrow = scr->hiRightArrow;
|
||||
else
|
||||
arrow = scr->rightArrow;
|
||||
} else {
|
||||
if (sPtr->flags.arrowsPosition == WSAMaxEnd) {
|
||||
ofs = view->size.height - bsize+1 - 3;
|
||||
} else {
|
||||
ofs = 2 + bsize+1;
|
||||
}
|
||||
if (sPtr->flags.incrDown)
|
||||
arrow = scr->hiDownArrow;
|
||||
else
|
||||
arrow = scr->downArrow;
|
||||
}
|
||||
|
||||
#ifndef DOUBLE_BUFFER
|
||||
if (sPtr->flags.incrDown)
|
||||
gc = scr->whiteGC;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (sPtr->flags.horizontal) {
|
||||
|
||||
/* paint button */
|
||||
#ifndef DOUBLE_BUFFER
|
||||
XFillRectangle(scr->display, d, gc,
|
||||
ofs+1, 2+1, bsize+1-3, bsize-3);
|
||||
#else
|
||||
if ((!part&&sPtr->flags.decrDown) || (part&&sPtr->flags.incrDown))
|
||||
XFillRectangle(scr->display, d, W_GC(scr->white),
|
||||
ofs+1, 2+1, bsize+1-3, bsize-3);
|
||||
#endif /* DOUBLE_BUFFER */
|
||||
W_DrawRelief(scr, d, ofs, 2, bsize, bsize, WRRaised);
|
||||
|
||||
/* paint arrow */
|
||||
XSetClipMask(scr->display, scr->clipGC, arrow->mask);
|
||||
XSetClipOrigin(scr->display, scr->clipGC,
|
||||
ofs + (bsize - arrow->width) / 2,
|
||||
2 + (bsize - arrow->height) / 2);
|
||||
|
||||
XCopyArea(scr->display, arrow->pixmap, d, scr->clipGC,
|
||||
0, 0, arrow->width, arrow->height,
|
||||
ofs + (bsize - arrow->width) / 2,
|
||||
2 + (bsize - arrow->height) / 2);
|
||||
|
||||
} else { /* vertical */
|
||||
|
||||
/* paint button */
|
||||
#ifndef DOUBLE_BUFFER
|
||||
XFillRectangle(scr->display, d, gc,
|
||||
2+1, ofs+1, bsize-3, bsize+1-3);
|
||||
#else
|
||||
if ((!part&&sPtr->flags.decrDown) || (part&&sPtr->flags.incrDown))
|
||||
XFillRectangle(scr->display, d, W_GC(scr->white),
|
||||
2+1, ofs+1, bsize-3, bsize+1-3);
|
||||
#endif /* DOUBLE_BUFFER */
|
||||
W_DrawRelief(scr, d, 2, ofs, bsize, bsize, WRRaised);
|
||||
|
||||
/* paint arrow */
|
||||
|
||||
XSetClipMask(scr->display, scr->clipGC, arrow->mask);
|
||||
XSetClipOrigin(scr->display, scr->clipGC,
|
||||
2 + (bsize - arrow->width) / 2,
|
||||
ofs + (bsize - arrow->height) / 2);
|
||||
XCopyArea(scr->display, arrow->pixmap, d, scr->clipGC,
|
||||
0, 0, arrow->width, arrow->height,
|
||||
2 + (bsize - arrow->width) / 2,
|
||||
ofs + (bsize - arrow->height) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
knobLength(Scroller *sPtr)
|
||||
{
|
||||
int tmp, length;
|
||||
|
||||
|
||||
if (sPtr->flags.horizontal)
|
||||
length = sPtr->view->size.width - 4;
|
||||
else
|
||||
length = sPtr->view->size.height - 4;
|
||||
|
||||
if (sPtr->flags.arrowsPosition == WSAMaxEnd) {
|
||||
length -= (SCROLLER_WIDTH - 4 + 1)*2;
|
||||
} else if (sPtr->flags.arrowsPosition == WSAMinEnd) {
|
||||
length -= (SCROLLER_WIDTH - 4 + 1)*2;
|
||||
}
|
||||
|
||||
tmp = (int)((float)length * sPtr->knobProportion + 0.5);
|
||||
/* keep minimum size */
|
||||
if (tmp < SCROLLER_WIDTH-4)
|
||||
tmp = SCROLLER_WIDTH-4;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintScroller(Scroller *sPtr)
|
||||
{
|
||||
WMView *view = sPtr->view;
|
||||
WMScreen *scr = view->screen;
|
||||
#ifdef DOUBLE_BUFFER
|
||||
Pixmap d;
|
||||
#else
|
||||
Drawable d = view->window;
|
||||
#endif
|
||||
int length, ofs;
|
||||
float knobP, knobL;
|
||||
|
||||
|
||||
#ifdef DOUBLE_BUFFER
|
||||
d = XCreatePixmap(scr->display, view->window, view->size.width,
|
||||
view->size.height, scr->depth);
|
||||
XFillRectangle(scr->display, d, W_GC(scr->gray), 0, 0,
|
||||
view->size.width, view->size.height);
|
||||
#endif
|
||||
|
||||
XDrawRectangle(scr->display, d, W_GC(scr->black), 0, 0,
|
||||
view->size.width-1, view->size.height-1);
|
||||
#ifndef DOUBLE_BUFFER
|
||||
XDrawRectangle(scr->display, d, W_GC(scr->gray), 1, 1,
|
||||
view->size.width-3, view->size.height-3);
|
||||
#endif
|
||||
|
||||
if (sPtr->flags.horizontal)
|
||||
length = view->size.width - 4;
|
||||
else
|
||||
length = view->size.height - 4;
|
||||
|
||||
if (sPtr->flags.documentFullyVisible) {
|
||||
XFillRectangle(scr->display, d, scr->stippleGC, 2, 2,
|
||||
view->size.width-4, view->size.height-4);
|
||||
} else {
|
||||
if (sPtr->flags.arrowsPosition==WSAMaxEnd) {
|
||||
ofs = 0;
|
||||
length -= (SCROLLER_WIDTH - 4 + 1)*2;
|
||||
} else if (sPtr->flags.arrowsPosition==WSAMinEnd) {
|
||||
ofs = (SCROLLER_WIDTH - 4 + 1)*2;
|
||||
length -= (SCROLLER_WIDTH - 4 + 1)*2;
|
||||
} else {
|
||||
ofs = 0;
|
||||
}
|
||||
|
||||
knobL = (float)knobLength(sPtr);
|
||||
|
||||
knobP = sPtr->floatValue * ((float)length - knobL);
|
||||
|
||||
|
||||
if (sPtr->flags.horizontal) {
|
||||
/* before */
|
||||
XFillRectangle(scr->display, d, scr->stippleGC,
|
||||
ofs+2, 2, (int)knobP, view->size.height-4);
|
||||
|
||||
/* knob */
|
||||
#ifndef DOUBLE_BUFFER
|
||||
XFillRectangle(scr->display, d, scr->lightGC,
|
||||
ofs+2+(int)knobP+2, 2+2, (int)knobL-4,
|
||||
view->size.height-4-4);
|
||||
#endif
|
||||
W_DrawRelief(scr, d, ofs+2+(int)knobP, 2, (int)knobL,
|
||||
view->size.height-4, WRRaised);
|
||||
|
||||
XCopyArea(scr->display, scr->scrollerDimple->pixmap, d,
|
||||
scr->copyGC, 0, 0,
|
||||
scr->scrollerDimple->width, scr->scrollerDimple->height,
|
||||
ofs+2+(int)knobP+((int)knobL-scr->scrollerDimple->width-1)/2,
|
||||
(view->size.height-scr->scrollerDimple->height-1)/2);
|
||||
|
||||
/* after */
|
||||
if ((int)(knobP+knobL) < length)
|
||||
XFillRectangle(scr->display, d, scr->stippleGC,
|
||||
ofs+2+(int)(knobP+knobL), 2,
|
||||
length-(int)(knobP+knobL),
|
||||
view->size.height-4);
|
||||
} else {
|
||||
/* before */
|
||||
if (knobP>0.0)
|
||||
XFillRectangle(scr->display, d, scr->stippleGC,
|
||||
2, ofs+2, view->size.width-4, (int)knobP);
|
||||
|
||||
/* knob */
|
||||
#ifndef DOUBLE_BUFFER
|
||||
XFillRectangle(scr->display, d, scr->lightGC,
|
||||
2+2, ofs+2+(int)knobP+2,
|
||||
view->size.width-4-4, (int)knobL-4);
|
||||
#endif
|
||||
XCopyArea(scr->display, scr->scrollerDimple->pixmap, d,
|
||||
scr->copyGC, 0, 0,
|
||||
scr->scrollerDimple->width, scr->scrollerDimple->height,
|
||||
(view->size.width-scr->scrollerDimple->width-1)/2,
|
||||
ofs+2+(int)knobP+((int)knobL-scr->scrollerDimple->height-1)/2);
|
||||
|
||||
W_DrawRelief(scr, d, 2, ofs+2+(int)knobP,
|
||||
view->size.width-4, (int)knobL, WRRaised);
|
||||
|
||||
/* after */
|
||||
if ((int)(knobP+knobL) < length)
|
||||
XFillRectangle(scr->display, d, scr->stippleGC,
|
||||
2, ofs+2+(int)(knobP+knobL),
|
||||
view->size.width-4,
|
||||
length-(int)(knobP+knobL));
|
||||
}
|
||||
|
||||
if (sPtr->flags.arrowsPosition != WSANone) {
|
||||
paintArrow(sPtr, d, 0);
|
||||
paintArrow(sPtr, d, 1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DOUBLE_BUFFER
|
||||
XCopyArea(scr->display, d, view->window, scr->copyGC, 0, 0,
|
||||
view->size.width, view->size.height, 0, 0);
|
||||
XFreePixmap(scr->display, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
Scroller *sPtr = (Scroller*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_Scroller);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count==0)
|
||||
paintScroller(sPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyScroller(sPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* locatePointInScroller-
|
||||
* Return the part of the scroller where the point is located.
|
||||
*/
|
||||
static WMScrollerPart
|
||||
locatePointInScroller(Scroller *sPtr, int x, int y, int alternate)
|
||||
{
|
||||
int width = sPtr->view->size.width;
|
||||
int height = sPtr->view->size.height;
|
||||
int c, p1, p2, p3, p4, p5, p6;
|
||||
int knobL, slotL;
|
||||
|
||||
|
||||
/* if there is no knob... */
|
||||
if (sPtr->flags.documentFullyVisible)
|
||||
return WSKnobSlot;
|
||||
|
||||
if (sPtr->flags.horizontal)
|
||||
c = x;
|
||||
else
|
||||
c = y;
|
||||
|
||||
/* p1 p2 p3 p4 p5 p6
|
||||
* | | |###########| |#####| | |
|
||||
* | < | > |###########| O |#####| < | > |
|
||||
* | | |###########| |#####| | |
|
||||
*/
|
||||
|
||||
if (sPtr->flags.arrowsPosition == WSAMinEnd) {
|
||||
p1 = 18;
|
||||
p2 = 36;
|
||||
|
||||
if (sPtr->flags.horizontal) {
|
||||
slotL = width - 36;
|
||||
p5 = width;
|
||||
} else {
|
||||
slotL = height - 36;
|
||||
p5 = height;
|
||||
}
|
||||
p6 = p5;
|
||||
} else if (sPtr->flags.arrowsPosition == WSAMaxEnd) {
|
||||
if (sPtr->flags.horizontal) {
|
||||
slotL = width - 36;
|
||||
p6 = width - 18;
|
||||
} else {
|
||||
slotL = height - 36;
|
||||
p6 = height - 18;
|
||||
}
|
||||
p5 = p6 - 18;
|
||||
|
||||
p1 = p2 = 0;
|
||||
} else {
|
||||
/* no arrows */
|
||||
p1 = p2 = 0;
|
||||
|
||||
if (sPtr->flags.horizontal) {
|
||||
slotL = p5 = p6 = width;
|
||||
} else {
|
||||
slotL = p5 = p6 = height;
|
||||
}
|
||||
}
|
||||
|
||||
knobL = knobLength(sPtr);
|
||||
p3 = p2 + (int)((float)(slotL-knobL) * sPtr->floatValue);
|
||||
p4 = p3 + knobL;
|
||||
|
||||
/* uses a mix of the NS and Win ways of doing scroll page */
|
||||
if (c <= p1)
|
||||
return alternate ? WSDecrementPage : WSDecrementLine;
|
||||
else if (c <= p2)
|
||||
return alternate ? WSIncrementPage : WSIncrementLine;
|
||||
else if (c <= p3)
|
||||
return WSDecrementPage;
|
||||
else if (c <= p4)
|
||||
return WSKnob;
|
||||
else if (c <= p5)
|
||||
return WSIncrementPage;
|
||||
else if (c <= p6)
|
||||
return alternate ? WSDecrementPage : WSDecrementLine;
|
||||
else
|
||||
return alternate ? WSIncrementPage : WSIncrementLine;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handlePush(Scroller *sPtr, int pushX, int pushY, int alternate)
|
||||
{
|
||||
WMScrollerPart part;
|
||||
int doAction = 0;
|
||||
|
||||
part = locatePointInScroller(sPtr, pushX, pushY, alternate);
|
||||
|
||||
sPtr->flags.hitPart = part;
|
||||
|
||||
switch (part) {
|
||||
case WSIncrementLine:
|
||||
sPtr->flags.incrDown = 1;
|
||||
doAction = 1;
|
||||
break;
|
||||
|
||||
case WSIncrementPage:
|
||||
doAction = 1;
|
||||
break;
|
||||
|
||||
case WSDecrementLine:
|
||||
sPtr->flags.decrDown = 1;
|
||||
doAction = 1;
|
||||
break;
|
||||
|
||||
case WSDecrementPage:
|
||||
doAction = 1;
|
||||
break;
|
||||
|
||||
case WSKnob:
|
||||
sPtr->flags.draggingKnob = 1;
|
||||
#ifndef STRICT_NEXT_BEHAVIOUR
|
||||
if (sPtr->flags.horizontal)
|
||||
sPtr->dragPoint = pushX;
|
||||
else
|
||||
sPtr->dragPoint = pushY;
|
||||
|
||||
{
|
||||
int noButtons = (sPtr->flags.arrowsPosition == WSANone);
|
||||
int length, knobP;
|
||||
|
||||
if (sPtr->flags.horizontal)
|
||||
length = sPtr->view->size.width - 4;
|
||||
else
|
||||
length = sPtr->view->size.height - 4;
|
||||
|
||||
if (!noButtons)
|
||||
length -= 36;
|
||||
|
||||
knobP = (int)(sPtr->floatValue * (float)(length-knobLength(sPtr)));
|
||||
|
||||
if (sPtr->flags.arrowsPosition == WSAMinEnd)
|
||||
sPtr->dragPoint -= 2 + (noButtons ? 0 : 36) + knobP;
|
||||
else
|
||||
sPtr->dragPoint -= 2 + knobP;
|
||||
}
|
||||
#endif /* STRICT_NEXT_BEHAVIOUR */
|
||||
handleMotion(sPtr, pushX, pushY);
|
||||
break;
|
||||
|
||||
case WSKnobSlot:
|
||||
case WSNoPart:
|
||||
/* dummy */
|
||||
break;
|
||||
}
|
||||
|
||||
if (doAction && sPtr->action) {
|
||||
(*sPtr->action)(sPtr, sPtr->clientData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static float
|
||||
floatValueForPoint(int slotOfs, int slotLength, int knobLength, int point)
|
||||
{
|
||||
float floatValue = 0;
|
||||
float position;
|
||||
|
||||
#ifdef STRICT_NEXT_BEHAVIOUR
|
||||
if (point < slotOfs + knobLength/2)
|
||||
position = (float)(slotOfs + knobLength/2);
|
||||
else if (point > slotOfs + slotLength - knobLength/2)
|
||||
position = (float)(slotOfs + slotLength - knobLength/2);
|
||||
else
|
||||
position = (float)point;
|
||||
|
||||
floatValue = (position-(float)(slotOfs+slotLength/2))
|
||||
/(float)(slotLength-knobLength);
|
||||
#else
|
||||
/* Adjust the last point to lie inside the knob slot */
|
||||
if (point < slotOfs)
|
||||
position = (float)slotOfs;
|
||||
else if (point > slotOfs + slotLength)
|
||||
position = (float)(slotOfs + slotLength);
|
||||
else
|
||||
position = (float)point;
|
||||
|
||||
/* Compute the float value */
|
||||
floatValue = (position-(float)slotOfs) / (float)(slotLength-knobLength);
|
||||
#endif
|
||||
|
||||
return floatValue;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleMotion(Scroller *sPtr, int mouseX, int mouseY)
|
||||
{
|
||||
int slotOffset;
|
||||
int slotLength;
|
||||
int noButtons = (sPtr->flags.arrowsPosition == WSANone);
|
||||
|
||||
if (sPtr->flags.arrowsPosition == WSAMinEnd)
|
||||
slotOffset = 2 + (noButtons ? 0 : 36);
|
||||
else
|
||||
slotOffset = 2;
|
||||
|
||||
if (sPtr->flags.draggingKnob) {
|
||||
float newFloatValue;
|
||||
#ifdef STRICT_NEXT_BEHAVIOUR
|
||||
if (sPtr->flags.horizontal) {
|
||||
slotLength = sPtr->view->size.width-4-(noButtons ? 0 : 36);
|
||||
newFloatValue = floatValueForPoint(slotOffset, slotLength,
|
||||
(int)(slotLength*sPtr->knobProportion),
|
||||
mouseX);
|
||||
} else {
|
||||
slotLength = sPtr->view->size.height-4-(noButtons ? 0 : 36);
|
||||
newFloatValue = floatValueForPoint(slotOffset, slotLength,
|
||||
(int)(slotLength*sPtr->knobProportion),
|
||||
mouseY);
|
||||
}
|
||||
#else
|
||||
if (sPtr->flags.horizontal) {
|
||||
slotLength = sPtr->view->size.width-4-(noButtons ? 0 : 36);
|
||||
newFloatValue = floatValueForPoint(slotOffset, slotLength,
|
||||
(int)(slotLength*sPtr->knobProportion),
|
||||
mouseX-sPtr->dragPoint);
|
||||
} else {
|
||||
slotLength = sPtr->view->size.height-4-(noButtons ? 0 : 36);
|
||||
newFloatValue = floatValueForPoint(slotOffset, slotLength,
|
||||
(int)(slotLength*sPtr->knobProportion),
|
||||
mouseY-sPtr->dragPoint);
|
||||
}
|
||||
#endif /* !STRICT_NEXT_BEHAVIOUR */
|
||||
WMSetScrollerParameters(sPtr, newFloatValue, sPtr->knobProportion);
|
||||
if (sPtr->action) {
|
||||
(*sPtr->action)(sPtr, sPtr->clientData);
|
||||
}
|
||||
} else {
|
||||
int part;
|
||||
|
||||
part = locatePointInScroller(sPtr, mouseX, mouseY, False);
|
||||
|
||||
sPtr->flags.hitPart = part;
|
||||
|
||||
if (part == WSIncrementLine && sPtr->flags.decrDown) {
|
||||
sPtr->flags.decrDown = 0;
|
||||
sPtr->flags.incrDown = 1;
|
||||
} else if (part == WSDecrementLine && sPtr->flags.incrDown) {
|
||||
sPtr->flags.incrDown = 0;
|
||||
sPtr->flags.decrDown = 1;
|
||||
} else if (part != WSIncrementLine && part != WSDecrementLine) {
|
||||
sPtr->flags.incrDown = 0;
|
||||
sPtr->flags.decrDown = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
autoScroll(void *clientData)
|
||||
{
|
||||
Scroller *sPtr = (Scroller*)clientData;
|
||||
|
||||
if (sPtr->action) {
|
||||
(*sPtr->action)(sPtr, sPtr->clientData);
|
||||
}
|
||||
sPtr->timerID= WMAddTimerHandler(AUTOSCROLL_DELAY, autoScroll, clientData);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
Scroller *sPtr = (Scroller*)data;
|
||||
int id, dd;
|
||||
|
||||
|
||||
/* check if we're really dealing with a scroller, as something
|
||||
* might have gone wrong in the event dispatching stuff */
|
||||
CHECK_CLASS(sPtr, WC_Scroller);
|
||||
|
||||
id = sPtr->flags.incrDown;
|
||||
dd = sPtr->flags.decrDown;
|
||||
|
||||
switch (event->type) {
|
||||
case EnterNotify:
|
||||
|
||||
break;
|
||||
|
||||
case LeaveNotify:
|
||||
if (sPtr->timerID) {
|
||||
WMDeleteTimerHandler(sPtr->timerID);
|
||||
sPtr->timerID = NULL;
|
||||
}
|
||||
sPtr->flags.incrDown = 0;
|
||||
sPtr->flags.decrDown = 0;
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
/* FIXME: change Mod1Mask with something else */
|
||||
handlePush(sPtr, event->xbutton.x, event->xbutton.y,
|
||||
(event->xbutton.state & Mod1Mask)
|
||||
||event->xbutton.button==Button2);
|
||||
/* continue scrolling if pushed on the buttons */
|
||||
if (sPtr->flags.hitPart == WSIncrementLine
|
||||
|| sPtr->flags.hitPart == WSDecrementLine) {
|
||||
sPtr->timerID = WMAddTimerHandler(AUTOSCROLL_INITIAL_DELAY,
|
||||
autoScroll, sPtr);
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
if (sPtr->flags.draggingKnob) {
|
||||
if (sPtr->action) {
|
||||
(*sPtr->action)(sPtr, sPtr->clientData);
|
||||
}
|
||||
}
|
||||
if (sPtr->timerID) {
|
||||
WMDeleteTimerHandler(sPtr->timerID);
|
||||
sPtr->timerID = NULL;
|
||||
}
|
||||
sPtr->flags.incrDown = 0;
|
||||
sPtr->flags.decrDown = 0;
|
||||
sPtr->flags.draggingKnob = 0;
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
handleMotion(sPtr, event->xbutton.x, event->xbutton.y);
|
||||
if (sPtr->timerID && sPtr->flags.hitPart != WSIncrementLine
|
||||
&& sPtr->flags.hitPart != WSDecrementLine) {
|
||||
WMDeleteTimerHandler(sPtr->timerID);
|
||||
sPtr->timerID = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (id != sPtr->flags.incrDown || dd != sPtr->flags.decrDown)
|
||||
paintScroller(sPtr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroyScroller(Scroller *sPtr)
|
||||
{
|
||||
/* we don't want autoscroll try to scroll a freed widget */
|
||||
if (sPtr->timerID) {
|
||||
WMDeleteTimerHandler(sPtr->timerID);
|
||||
}
|
||||
|
||||
free(sPtr);
|
||||
}
|
||||
|
||||
501
WINGs/wscrollview.c
Normal file
501
WINGs/wscrollview.c
Normal file
@@ -0,0 +1,501 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
typedef struct W_ScrollView {
|
||||
W_Class widgetClass;
|
||||
WMView *view;
|
||||
|
||||
WMView *contentView;
|
||||
WMView *viewport;
|
||||
|
||||
WMScroller *vScroller;
|
||||
WMScroller *hScroller;
|
||||
|
||||
short lineScroll;
|
||||
short pageScroll;
|
||||
|
||||
struct {
|
||||
WMReliefType relief:3;
|
||||
unsigned int hasVScroller:1;
|
||||
unsigned int hasHScroller:1;
|
||||
|
||||
} flags;
|
||||
|
||||
} ScrollView;
|
||||
|
||||
|
||||
|
||||
|
||||
static void destroyScrollView(ScrollView *sPtr);
|
||||
|
||||
static void paintScrollView(ScrollView *sPtr);
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleViewportEvents(XEvent *event, void *data);
|
||||
static void resizeScrollView();
|
||||
|
||||
|
||||
W_ViewProcedureTable _ScrollViewViewProcedures = {
|
||||
NULL,
|
||||
resizeScrollView,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
WMScrollView*
|
||||
WMCreateScrollView(WMWidget *parent)
|
||||
{
|
||||
ScrollView *sPtr;
|
||||
|
||||
sPtr = wmalloc(sizeof(ScrollView));
|
||||
memset(sPtr, 0, sizeof(ScrollView));
|
||||
|
||||
sPtr->widgetClass = WC_ScrollView;
|
||||
|
||||
sPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!sPtr->view) {
|
||||
free(sPtr);
|
||||
return NULL;
|
||||
}
|
||||
sPtr->viewport = W_CreateView(sPtr->view);
|
||||
if (!sPtr->view) {
|
||||
W_DestroyView(sPtr->view);
|
||||
free(sPtr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sPtr->viewport->flags.mapWhenRealized = 1;
|
||||
|
||||
WMCreateEventHandler(sPtr->view, StructureNotifyMask|ExposureMask,
|
||||
handleEvents, sPtr);
|
||||
WMCreateEventHandler(sPtr->viewport, SubstructureNotifyMask,
|
||||
handleViewportEvents, sPtr);
|
||||
|
||||
sPtr->lineScroll = 4;
|
||||
|
||||
sPtr->pageScroll = 0;
|
||||
|
||||
return sPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
reorganizeInterior(WMScrollView *sPtr)
|
||||
{
|
||||
int hx, hy, hw;
|
||||
int vx, vy, vh;
|
||||
int cx, cy, cw, ch;
|
||||
|
||||
|
||||
cw = hw = sPtr->view->size.width;
|
||||
vh = ch = sPtr->view->size.height;
|
||||
|
||||
if (sPtr->flags.relief == WRSimple) {
|
||||
cw -= 2;
|
||||
ch -= 2;
|
||||
cx = 1;
|
||||
cy = 1;
|
||||
} else if (sPtr->flags.relief != WRFlat) {
|
||||
cw -= 3;
|
||||
ch -= 3;
|
||||
cx = 2;
|
||||
cy = 2;
|
||||
} else {
|
||||
cx = 0;
|
||||
cy = 0;
|
||||
}
|
||||
|
||||
if (sPtr->flags.hasHScroller) {
|
||||
int h = W_VIEW(sPtr->hScroller)->size.height;
|
||||
|
||||
ch -= h;
|
||||
|
||||
if (sPtr->flags.relief == WRSimple) {
|
||||
hx = 0;
|
||||
hy = sPtr->view->size.height - h;
|
||||
} else if (sPtr->flags.relief != WRFlat) {
|
||||
hx = 1;
|
||||
hy = sPtr->view->size.height - h - 1;
|
||||
hw -= 2;
|
||||
} else {
|
||||
hx = 0;
|
||||
hy = sPtr->view->size.height - h;
|
||||
}
|
||||
} else {
|
||||
/* make compiler shutup */
|
||||
hx = 0;
|
||||
hy = 0;
|
||||
}
|
||||
|
||||
if (sPtr->flags.hasVScroller) {
|
||||
int w = W_VIEW(sPtr->vScroller)->size.width;
|
||||
cw -= w;
|
||||
cx += w;
|
||||
hx += w - 1;
|
||||
hw -= w - 1;
|
||||
|
||||
if (sPtr->flags.relief == WRSimple) {
|
||||
vx = 0;
|
||||
vy = 0;
|
||||
} else if (sPtr->flags.relief != WRFlat) {
|
||||
vx = 1;
|
||||
vy = 1;
|
||||
vh -= 2;
|
||||
} else {
|
||||
vx = 0;
|
||||
vy = 0;
|
||||
}
|
||||
} else {
|
||||
/* make compiler shutup */
|
||||
vx = 0;
|
||||
vy = 0;
|
||||
}
|
||||
|
||||
W_ResizeView(sPtr->viewport, cw, ch);
|
||||
W_MoveView(sPtr->viewport, cx, cy);
|
||||
|
||||
if (sPtr->flags.hasHScroller) {
|
||||
WMResizeWidget(sPtr->hScroller, hw, 20);
|
||||
WMMoveWidget(sPtr->hScroller, hx, hy);
|
||||
}
|
||||
if (sPtr->flags.hasVScroller) {
|
||||
WMResizeWidget(sPtr->vScroller, 20, vh);
|
||||
WMMoveWidget(sPtr->vScroller, vx, vy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resizeScrollView(WMScrollView *sPtr, unsigned int width, unsigned int height)
|
||||
{
|
||||
W_ResizeView(sPtr->view, width, height);
|
||||
|
||||
reorganizeInterior(sPtr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMResizeScrollViewContent(WMScrollView *sPtr, unsigned int width,
|
||||
unsigned int height)
|
||||
{
|
||||
int w, h, x;
|
||||
|
||||
w = width;
|
||||
h = height;
|
||||
|
||||
x = 0;
|
||||
if (sPtr->flags.relief == WRSimple) {
|
||||
w += 2;
|
||||
h += 2;
|
||||
} else if (sPtr->flags.relief != WRFlat) {
|
||||
w += 4;
|
||||
h += 4;
|
||||
x = 1;
|
||||
}
|
||||
|
||||
if (sPtr->flags.hasVScroller) {
|
||||
w -= W_VIEW(sPtr->hScroller)->size.width;
|
||||
WMResizeWidget(sPtr->vScroller, 20, h);
|
||||
}
|
||||
if (sPtr->flags.hasHScroller) {
|
||||
h -= W_VIEW(sPtr->hScroller)->size.height;
|
||||
WMResizeWidget(sPtr->hScroller, w, 20);
|
||||
WMMoveWidget(sPtr->hScroller, x, h);
|
||||
}
|
||||
|
||||
W_ResizeView(sPtr->view, w, h);
|
||||
|
||||
W_ResizeView(sPtr->viewport, width, height);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetScrollViewLineScroll(WMScrollView *sPtr, int amount)
|
||||
{
|
||||
assert(amount > 0);
|
||||
|
||||
sPtr->lineScroll = amount;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetScrollViewPageScroll(WMScrollView *sPtr, int amount)
|
||||
{
|
||||
assert(amount >= 0);
|
||||
|
||||
sPtr->pageScroll = amount;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
doScrolling(WMWidget *self, void *data)
|
||||
{
|
||||
ScrollView *sPtr = (ScrollView*)data;
|
||||
float value;
|
||||
int pos;
|
||||
int vpsize;
|
||||
float size;
|
||||
|
||||
if (sPtr->hScroller == self) {
|
||||
pos = -sPtr->contentView->pos.x;
|
||||
size = sPtr->contentView->size.width-sPtr->viewport->size.width;
|
||||
vpsize = sPtr->viewport->size.width - sPtr->pageScroll;
|
||||
} else {
|
||||
pos = -sPtr->contentView->pos.y;
|
||||
size = sPtr->contentView->size.height-sPtr->viewport->size.height;
|
||||
vpsize = sPtr->viewport->size.height - sPtr->pageScroll;
|
||||
}
|
||||
if (vpsize <= 0)
|
||||
vpsize = 1;
|
||||
|
||||
switch (WMGetScrollerHitPart(self)) {
|
||||
case WSDecrementLine:
|
||||
if (pos > 0) {
|
||||
pos-=sPtr->lineScroll;
|
||||
if (pos < 0)
|
||||
pos = 0;
|
||||
value = (float)pos / size;
|
||||
WMSetScrollerParameters(self, value,
|
||||
WMGetScrollerKnobProportion(self));
|
||||
}
|
||||
break;
|
||||
case WSIncrementLine:
|
||||
if (pos < size) {
|
||||
pos+=sPtr->lineScroll;
|
||||
if (pos > size)
|
||||
pos = size;
|
||||
value = (float)pos / size;
|
||||
WMSetScrollerParameters(self, value,
|
||||
WMGetScrollerKnobProportion(self));
|
||||
}
|
||||
break;
|
||||
case WSKnob:
|
||||
value = WMGetScrollerValue(self);
|
||||
pos = value*size;
|
||||
break;
|
||||
|
||||
case WSDecrementPage:
|
||||
if (pos > 0) {
|
||||
pos -= vpsize;
|
||||
if (pos < 0)
|
||||
pos = 0;
|
||||
value = (float)pos / size;
|
||||
WMSetScrollerParameters(self, value,
|
||||
WMGetScrollerKnobProportion(self));
|
||||
}
|
||||
break;
|
||||
|
||||
case WSIncrementPage:
|
||||
if (pos < size) {
|
||||
pos += vpsize;
|
||||
if (pos > size)
|
||||
pos = size;
|
||||
value = (float)pos / size;
|
||||
WMSetScrollerParameters(self, value,
|
||||
WMGetScrollerKnobProportion(self));
|
||||
}
|
||||
break;
|
||||
|
||||
case WSNoPart:
|
||||
case WSKnobSlot:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sPtr->hScroller == self) {
|
||||
W_MoveView(sPtr->contentView, -pos, sPtr->contentView->pos.y);
|
||||
} else {
|
||||
W_MoveView(sPtr->contentView, sPtr->contentView->pos.x, -pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMScroller*
|
||||
WMGetScrollViewHorizontalScroller(WMScrollView *sPtr)
|
||||
{
|
||||
return sPtr->hScroller;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMScroller*
|
||||
WMGetScrollViewVerticalScroller(WMScrollView *sPtr)
|
||||
{
|
||||
return sPtr->vScroller;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetScrollViewHasHorizontalScroller(WMScrollView *sPtr, Bool flag)
|
||||
{
|
||||
if (flag) {
|
||||
if (sPtr->flags.hasHScroller)
|
||||
return;
|
||||
sPtr->flags.hasHScroller = 1;
|
||||
|
||||
sPtr->hScroller = WMCreateScroller(sPtr);
|
||||
WMSetScrollerAction(sPtr->hScroller, doScrolling, sPtr);
|
||||
/* make it a horiz. scroller */
|
||||
WMResizeWidget(sPtr->hScroller, 2, 1);
|
||||
|
||||
reorganizeInterior(sPtr);
|
||||
|
||||
WMMapWidget(sPtr->hScroller);
|
||||
} else {
|
||||
if (!sPtr->flags.hasHScroller)
|
||||
return;
|
||||
|
||||
WMUnmapWidget(sPtr->hScroller);
|
||||
WMDestroyWidget(sPtr->hScroller);
|
||||
sPtr->hScroller = NULL;
|
||||
sPtr->flags.hasHScroller = 0;
|
||||
|
||||
reorganizeInterior(sPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetScrollViewHasVerticalScroller(WMScrollView *sPtr, Bool flag)
|
||||
{
|
||||
if (flag) {
|
||||
if (sPtr->flags.hasVScroller)
|
||||
return;
|
||||
sPtr->flags.hasVScroller = 1;
|
||||
|
||||
sPtr->vScroller = WMCreateScroller(sPtr);
|
||||
WMSetScrollerAction(sPtr->vScroller, doScrolling, sPtr);
|
||||
WMSetScrollerArrowsPosition(sPtr->vScroller, WSAMaxEnd);
|
||||
/* make it a vert. scroller */
|
||||
WMResizeWidget(sPtr->vScroller, 1, 2);
|
||||
|
||||
reorganizeInterior(sPtr);
|
||||
|
||||
WMMapWidget(sPtr->vScroller);
|
||||
} else {
|
||||
if (!sPtr->flags.hasVScroller)
|
||||
return;
|
||||
sPtr->flags.hasVScroller = 0;
|
||||
|
||||
WMUnmapWidget(sPtr->vScroller);
|
||||
WMDestroyWidget(sPtr->vScroller);
|
||||
sPtr->vScroller = NULL;
|
||||
|
||||
reorganizeInterior(sPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetScrollViewContentView(WMScrollView *sPtr, WMView *view)
|
||||
{
|
||||
assert(sPtr->contentView == NULL);
|
||||
|
||||
sPtr->contentView = view;
|
||||
|
||||
W_ReparentView(sPtr->contentView, sPtr->viewport);
|
||||
|
||||
if (sPtr->flags.hasHScroller) {
|
||||
float prop;
|
||||
|
||||
prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
|
||||
WMSetScrollerParameters(sPtr->hScroller, 0, prop);
|
||||
}
|
||||
if (sPtr->flags.hasVScroller) {
|
||||
float prop;
|
||||
|
||||
prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
|
||||
|
||||
WMSetScrollerParameters(sPtr->vScroller, 0, prop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetScrollViewRelief(WMScrollView *sPtr, WMReliefType type)
|
||||
{
|
||||
sPtr->flags.relief = type;
|
||||
|
||||
if (sPtr->view->flags.mapped)
|
||||
paintScrollView(sPtr);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintScrollView(ScrollView *sPtr)
|
||||
{
|
||||
W_DrawRelief(sPtr->view->screen, sPtr->view->window, 0, 0,
|
||||
sPtr->view->size.width, sPtr->view->size.height,
|
||||
sPtr->flags.relief);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
updateScrollerProportion(ScrollView *sPtr)
|
||||
{
|
||||
float prop, value;
|
||||
|
||||
if (sPtr->flags.hasHScroller) {
|
||||
prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
|
||||
value = WMGetScrollerValue(sPtr->hScroller);
|
||||
|
||||
WMSetScrollerParameters(sPtr->hScroller, value, prop);
|
||||
}
|
||||
if (sPtr->flags.hasVScroller) {
|
||||
prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
|
||||
|
||||
value = WMGetScrollerValue(sPtr->vScroller);
|
||||
|
||||
WMSetScrollerParameters(sPtr->vScroller, value, prop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleViewportEvents(XEvent *event, void *data)
|
||||
{
|
||||
ScrollView *sPtr = (ScrollView*)data;
|
||||
|
||||
if (sPtr->contentView
|
||||
&& event->xconfigure.window == sPtr->contentView->window)
|
||||
updateScrollerProportion(sPtr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
ScrollView *sPtr = (ScrollView*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_ScrollView);
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintScrollView(sPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyScrollView(sPtr);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
destroyScrollView(ScrollView *sPtr)
|
||||
{
|
||||
|
||||
|
||||
free(sPtr);
|
||||
}
|
||||
|
||||
482
WINGs/wslider.c
Normal file
482
WINGs/wslider.c
Normal file
@@ -0,0 +1,482 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
#undef STRICT_NEXT_BEHAVIOUR
|
||||
|
||||
|
||||
typedef struct W_Slider {
|
||||
W_Class widgetClass;
|
||||
WMView *view;
|
||||
|
||||
int minValue;
|
||||
int maxValue;
|
||||
|
||||
int value;
|
||||
|
||||
Pixmap knobPixmap;
|
||||
|
||||
WMAction *action;
|
||||
void *clientData;
|
||||
|
||||
struct {
|
||||
unsigned int continuous:1;
|
||||
|
||||
unsigned int vertical:1;
|
||||
unsigned int dragging:1;
|
||||
} flags;
|
||||
|
||||
} Slider;
|
||||
|
||||
|
||||
|
||||
#define SLIDER_LENGTH 20
|
||||
|
||||
|
||||
static void resizeSlider();
|
||||
|
||||
|
||||
W_ViewProcedureTable _SliderViewProcedures = {
|
||||
NULL,
|
||||
resizeSlider,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void destroySlider(Slider *sPtr);
|
||||
static void paintSlider(Slider *sPtr);
|
||||
static void realizeSlider(Slider *sPtr);
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleActionEvents(XEvent *event, void *data);
|
||||
|
||||
|
||||
static void
|
||||
realizeObserver(void *self, WMNotification *not)
|
||||
{
|
||||
realizeSlider(self);
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMSlider*
|
||||
WMCreateSlider(WMWidget *parent)
|
||||
{
|
||||
Slider *sPtr;
|
||||
|
||||
sPtr = wmalloc(sizeof(Slider));
|
||||
memset(sPtr, 0, sizeof(Slider));
|
||||
|
||||
sPtr->widgetClass = WC_Slider;
|
||||
|
||||
sPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!sPtr->view) {
|
||||
free(sPtr);
|
||||
return NULL;
|
||||
}
|
||||
sPtr->view->self = sPtr;
|
||||
|
||||
WMCreateEventHandler(sPtr->view, ExposureMask|StructureNotifyMask,
|
||||
handleEvents, sPtr);
|
||||
|
||||
|
||||
WMCreateEventHandler(sPtr->view, ButtonPressMask|ButtonReleaseMask
|
||||
|EnterWindowMask|LeaveWindowMask|ButtonMotionMask,
|
||||
handleActionEvents, sPtr);
|
||||
|
||||
W_ResizeView(sPtr->view, 100, 16);
|
||||
sPtr->flags.vertical = 0;
|
||||
sPtr->minValue = 0;
|
||||
sPtr->maxValue = 100;
|
||||
sPtr->value = 50;
|
||||
|
||||
sPtr->flags.continuous = 1;
|
||||
|
||||
WMAddNotificationObserver(realizeObserver, sPtr,
|
||||
WMViewRealizedNotification, sPtr->view);
|
||||
|
||||
return sPtr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
WMGetSliderMinValue(WMSlider *slider)
|
||||
{
|
||||
CHECK_CLASS(slider, WC_Slider);
|
||||
|
||||
return slider->minValue;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetSliderMaxValue(WMSlider *slider)
|
||||
{
|
||||
CHECK_CLASS(slider, WC_Slider);
|
||||
|
||||
return slider->maxValue;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMGetSliderValue(WMSlider *slider)
|
||||
{
|
||||
CHECK_CLASS(slider, WC_Slider);
|
||||
|
||||
return slider->value;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetSliderMinValue(WMSlider *slider, int value)
|
||||
{
|
||||
CHECK_CLASS(slider, WC_Slider);
|
||||
|
||||
slider->minValue = value;
|
||||
if (slider->value < value) {
|
||||
slider->value = value;
|
||||
if (slider->view->flags.mapped)
|
||||
paintSlider(slider);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetSliderMaxValue(WMSlider *slider, int value)
|
||||
{
|
||||
CHECK_CLASS(slider, WC_Slider);
|
||||
|
||||
slider->maxValue = value;
|
||||
if (slider->value > value) {
|
||||
slider->value = value;
|
||||
if (slider->view->flags.mapped)
|
||||
paintSlider(slider);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetSliderValue(WMSlider *slider, int value)
|
||||
{
|
||||
CHECK_CLASS(slider, WC_Slider);
|
||||
|
||||
if (value < slider->minValue)
|
||||
slider->value = slider->minValue;
|
||||
else if (value > slider->maxValue)
|
||||
slider->value = slider->maxValue;
|
||||
else
|
||||
slider->value = value;
|
||||
|
||||
if (slider->view->flags.mapped)
|
||||
paintSlider(slider);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetSliderContinuous(WMSlider *slider, Bool flag)
|
||||
{
|
||||
CHECK_CLASS(slider, WC_Slider);
|
||||
|
||||
slider->flags.continuous = flag;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetSliderAction(WMSlider *slider, WMAction *action, void *data)
|
||||
{
|
||||
CHECK_CLASS(slider, WC_Slider);
|
||||
|
||||
slider->action = action;
|
||||
slider->clientData = data;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
makeKnobPixmap(Slider *sPtr)
|
||||
{
|
||||
Pixmap pix;
|
||||
WMScreen *scr = sPtr->view->screen;
|
||||
int w, h;
|
||||
|
||||
if (sPtr->flags.vertical) {
|
||||
w = sPtr->view->size.width-2;
|
||||
h = SLIDER_LENGTH;
|
||||
} else {
|
||||
w = SLIDER_LENGTH;
|
||||
h = sPtr->view->size.height-2;
|
||||
}
|
||||
|
||||
pix = XCreatePixmap(scr->display, sPtr->view->window, w, h, scr->depth);
|
||||
XFillRectangle(scr->display, pix, W_GC(scr->gray), 0, 0, w, h);
|
||||
|
||||
if (sPtr->flags.vertical) {
|
||||
XDrawLine(scr->display, pix, W_GC(scr->white), 0, 0, 0, h-3);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->white), 1, 0, 1, h-3);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), w-2, 1, w-2, h/2-2);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), w-2, h/2, w-2, h-2);
|
||||
|
||||
XDrawLine(scr->display, pix, W_GC(scr->white), 0, 0, w-2, 0);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), 1, h/2-2, w-3, h/2-2);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->white), 0, h/2-1, w-3, h/2-1);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->black), w-1, 0, w-1, h-2);
|
||||
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), 0, h-3, w-2, h-3);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->black), 0, h-2, w-1, h-2);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), 0, h-1, w-1,h-1);
|
||||
} else {
|
||||
XDrawLine(scr->display, pix, W_GC(scr->white), 0, 0, w-3, 0);
|
||||
|
||||
XDrawLine(scr->display, pix, W_GC(scr->white), 0, 0, 0, h-2);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->white), 1, 0, 1, h-3);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), w/2-2, 1, w/2-2, h-3);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->white), w/2-1, 0, w/2-1, h-3);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), w-3, 0, w-3, h-2);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->black), w-2, 0, w-2, h-2);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), w-1, 0, w-1, h-1);
|
||||
|
||||
XDrawLine(scr->display, pix, W_GC(scr->black), 1, h-1, w/2+1, h-1);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), 1, h-2, w/2-2, h-2);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->darkGray), w/2, h-2, w-3,h-2);
|
||||
XDrawLine(scr->display, pix, W_GC(scr->black), 0, h-1, w-2, h-1);
|
||||
}
|
||||
|
||||
if (sPtr->knobPixmap)
|
||||
XFreePixmap(scr->display, sPtr->knobPixmap);
|
||||
sPtr->knobPixmap = pix;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
realizeSlider(Slider *sPtr)
|
||||
{
|
||||
W_RealizeView(sPtr->view);
|
||||
|
||||
makeKnobPixmap(sPtr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resizeSlider(Slider *sPtr, unsigned int width, unsigned int height)
|
||||
{
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
|
||||
W_ResizeView(sPtr->view, width, height);
|
||||
|
||||
if (width > height) {
|
||||
if (sPtr->flags.vertical) {
|
||||
sPtr->flags.vertical = 0;
|
||||
if (sPtr->view->flags.realized)
|
||||
makeKnobPixmap(sPtr);
|
||||
}
|
||||
} else {
|
||||
if (!sPtr->flags.vertical) {
|
||||
sPtr->flags.vertical = 1;
|
||||
if (sPtr->view->flags.realized)
|
||||
makeKnobPixmap(sPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
paintSlider(Slider *sPtr)
|
||||
{
|
||||
W_Screen *scr = sPtr->view->screen;
|
||||
GC bgc;
|
||||
GC wgc;
|
||||
GC lgc;
|
||||
WMSize size = sPtr->view->size;
|
||||
int pos;
|
||||
Pixmap buffer;
|
||||
|
||||
#define MINV sPtr->minValue
|
||||
#define MAXV sPtr->maxValue
|
||||
#define POSV sPtr->value
|
||||
|
||||
bgc = W_GC(scr->black);
|
||||
wgc = W_GC(scr->white);
|
||||
lgc = W_GC(scr->gray);
|
||||
|
||||
buffer = XCreatePixmap(scr->display, sPtr->view->window,
|
||||
size.width, size.height, scr->depth);
|
||||
XFillRectangle(scr->display, buffer, lgc, 0, 0, size.width, size.height);
|
||||
XFillRectangle(scr->display, buffer, scr->stippleGC, 0, 0, size.width,
|
||||
size.height);
|
||||
|
||||
if (sPtr->flags.vertical) {
|
||||
pos = (size.height-2-SLIDER_LENGTH)*(POSV-MINV)/(MAXV-MINV)+1;
|
||||
/* draw knob */
|
||||
XCopyArea(scr->display, sPtr->knobPixmap, buffer,
|
||||
scr->copyGC, 0, 0, size.width-2, SLIDER_LENGTH, 1, pos);
|
||||
} else {
|
||||
pos = (size.width-2-SLIDER_LENGTH)*(POSV-MINV)/(MAXV-MINV)+1;
|
||||
/* draw knob */
|
||||
XCopyArea(scr->display, sPtr->knobPixmap, buffer,
|
||||
scr->copyGC, 0, 0, SLIDER_LENGTH, size.height, pos, 1);
|
||||
}
|
||||
|
||||
XDrawLine(scr->display, buffer, bgc, 0, 0, 0, size.height-1);
|
||||
XDrawLine(scr->display, buffer, bgc, 0, 0, size.width, 0);
|
||||
|
||||
XDrawLine(scr->display, buffer, wgc, size.width-1, 0,
|
||||
size.width-1, size.height-1);
|
||||
XDrawLine(scr->display, buffer, wgc, 0, size.height-1,
|
||||
size.width-1, size.height-1);
|
||||
|
||||
XCopyArea(scr->display, buffer, sPtr->view->window, scr->copyGC, 0, 0,
|
||||
size.width, size.height, 0, 0);
|
||||
XFreePixmap(scr->display, buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
Slider *sPtr = (Slider*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_Slider);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintSlider(sPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroySlider(sPtr);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define DECR_PART 1
|
||||
#define KNOB_PART 2
|
||||
#define INCR_PART 3
|
||||
|
||||
static int
|
||||
getSliderPart(Slider *sPtr, int x, int y)
|
||||
{
|
||||
int p;
|
||||
int pos;
|
||||
WMSize size = sPtr->view->size;
|
||||
|
||||
|
||||
if (sPtr->flags.vertical) {
|
||||
p = y;
|
||||
pos = (size.height-2-SLIDER_LENGTH)*(POSV-MINV)/(MAXV-MINV);
|
||||
if (p < pos)
|
||||
return INCR_PART;
|
||||
if (p > pos + SLIDER_LENGTH)
|
||||
return DECR_PART;
|
||||
return KNOB_PART;
|
||||
} else {
|
||||
p = x;
|
||||
pos = (size.width-2-SLIDER_LENGTH)*(POSV-MINV)/(MAXV-MINV);
|
||||
if (p < pos)
|
||||
return DECR_PART;
|
||||
if (p > pos + SLIDER_LENGTH)
|
||||
return INCR_PART;
|
||||
return KNOB_PART;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
valueForMousePoint(Slider *sPtr, int x, int y)
|
||||
{
|
||||
WMSize size = sPtr->view->size;
|
||||
int f;
|
||||
|
||||
if (sPtr->flags.vertical) {
|
||||
f = (y-SLIDER_LENGTH/2)*(MAXV-MINV)/((int)size.height-2-SLIDER_LENGTH);
|
||||
} else {
|
||||
f = (x-SLIDER_LENGTH/2)*(MAXV-MINV)/((int)size.width-2-SLIDER_LENGTH);
|
||||
}
|
||||
|
||||
f += sPtr->minValue;
|
||||
if (f < sPtr->minValue)
|
||||
f = sPtr->minValue;
|
||||
else if (f > sPtr->maxValue)
|
||||
f = sPtr->maxValue;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
WMSlider *sPtr = (Slider*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_Slider);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case ButtonPress:
|
||||
if (getSliderPart(sPtr, event->xbutton.x, event->xbutton.y)==KNOB_PART)
|
||||
sPtr->flags.dragging = 1;
|
||||
else {
|
||||
#ifdef STRICT_NEXT_BEHAVIOUR
|
||||
sPtr->flags.dragging = 1;
|
||||
|
||||
sPtr->value = valueForMousePoint(sPtr, event->xmotion.x,
|
||||
event->xmotion.y);
|
||||
paintSlider(sPtr);
|
||||
#else
|
||||
int tmp;
|
||||
|
||||
tmp = valueForMousePoint(sPtr, event->xmotion.x, event->xmotion.y);
|
||||
if (tmp < sPtr->value)
|
||||
tmp = sPtr->value-1;
|
||||
else
|
||||
tmp = sPtr->value+1;
|
||||
WMSetSliderValue(sPtr, tmp);
|
||||
#endif
|
||||
|
||||
if (sPtr->flags.continuous && sPtr->action) {
|
||||
(*sPtr->action)(sPtr, sPtr->clientData);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
if (!sPtr->flags.continuous && sPtr->flags.dragging && sPtr->action) {
|
||||
(*sPtr->action)(sPtr, sPtr->clientData);
|
||||
}
|
||||
sPtr->flags.dragging = 0;
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
if (sPtr->flags.dragging) {
|
||||
sPtr->value = valueForMousePoint(sPtr, event->xmotion.x,
|
||||
event->xmotion.y);
|
||||
paintSlider(sPtr);
|
||||
|
||||
if (sPtr->flags.continuous && sPtr->action) {
|
||||
(*sPtr->action)(sPtr, sPtr->clientData);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroySlider(Slider *sPtr)
|
||||
{
|
||||
if (sPtr->knobPixmap)
|
||||
XFreePixmap(sPtr->view->screen->display, sPtr->knobPixmap);
|
||||
|
||||
free(sPtr);
|
||||
}
|
||||
|
||||
402
WINGs/wsplitview.c
Normal file
402
WINGs/wsplitview.c
Normal file
@@ -0,0 +1,402 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct W_SplitView {
|
||||
W_Class widgetClass;
|
||||
W_View *view;
|
||||
|
||||
/* WMSplitViewResizeSubviewsProc *resizeSubviewsProc;
|
||||
*/
|
||||
WMSplitViewConstrainProc *constrainProc;
|
||||
|
||||
struct {
|
||||
unsigned int splitViewIsFull:1; /* already added 2 subviews */
|
||||
} flags;
|
||||
} SplitView;
|
||||
|
||||
|
||||
#define DIVIDER_THICKNESS 8
|
||||
|
||||
|
||||
|
||||
static void destroySplitView(SplitView *sPtr);
|
||||
static void paintSplitView(SplitView *sPtr);
|
||||
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleActionEvents(XEvent *event, void *data);
|
||||
|
||||
|
||||
W_ViewProcedureTable _SplitViewViewProcedures = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int
|
||||
subviewCount(SplitView *sPtr)
|
||||
{
|
||||
int count = 0;
|
||||
WMView *view;
|
||||
|
||||
for (view=sPtr->view->childrenList; view != NULL; view=view->nextSister)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleViewResized(void *self, WMNotification *notification)
|
||||
{
|
||||
SplitView *sPtr = (SplitView*)self;
|
||||
int oldHeight;
|
||||
WMView *view = sPtr->view;
|
||||
int newWidth = view->size.width;
|
||||
WMView *upper, *lower;
|
||||
|
||||
if (!view->childrenList)
|
||||
return;
|
||||
|
||||
if (view->childrenList->nextSister==NULL) {
|
||||
if (view->self)
|
||||
WMResizeWidget(view->childrenList->self, newWidth, view->size.height);
|
||||
else
|
||||
W_ResizeView(view->childrenList, newWidth, view->size.height);
|
||||
} else {
|
||||
upper = view->childrenList;
|
||||
lower = upper->nextSister;
|
||||
oldHeight = upper->size.height+DIVIDER_THICKNESS+lower->size.height;
|
||||
|
||||
if (oldHeight > view->size.height
|
||||
&& upper->size.height+DIVIDER_THICKNESS >= view->size.height) {
|
||||
WMAdjustSplitViewSubviews(sPtr);
|
||||
} else {
|
||||
if (upper->self) {
|
||||
WMResizeWidget(upper->self, newWidth, upper->size.height);
|
||||
} else {
|
||||
W_ResizeView(upper, newWidth, upper->size.height);
|
||||
}
|
||||
if (lower->self) {
|
||||
WMResizeWidget(lower->self, newWidth,
|
||||
view->size.height-lower->pos.y);
|
||||
} else {
|
||||
W_ResizeView(lower, newWidth, view->size.height-lower->pos.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMSplitView*
|
||||
WMCreateSplitView(WMWidget *parent)
|
||||
{
|
||||
SplitView *sPtr;
|
||||
|
||||
sPtr = wmalloc(sizeof(SplitView));
|
||||
memset(sPtr, 0, sizeof(SplitView));
|
||||
|
||||
sPtr->widgetClass = WC_SplitView;
|
||||
|
||||
sPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!sPtr->view) {
|
||||
free(sPtr);
|
||||
return NULL;
|
||||
}
|
||||
sPtr->view->self = sPtr;
|
||||
|
||||
WMSetViewNotifySizeChanges(sPtr->view, True);
|
||||
|
||||
WMCreateEventHandler(sPtr->view, ExposureMask|StructureNotifyMask
|
||||
|ClientMessageMask, handleEvents, sPtr);
|
||||
|
||||
|
||||
WMCreateEventHandler(sPtr->view, ButtonPressMask|ButtonReleaseMask
|
||||
|EnterWindowMask|LeaveWindowMask,
|
||||
handleActionEvents, sPtr);
|
||||
|
||||
|
||||
WMAddNotificationObserver(handleViewResized, sPtr,
|
||||
WMViewSizeDidChangeNotification, sPtr->view);
|
||||
|
||||
return sPtr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMAddSplitViewSubview(WMSplitView *sPtr, WMView *subview)
|
||||
{
|
||||
int wasMapped;
|
||||
|
||||
assert(!sPtr->flags.splitViewIsFull);
|
||||
|
||||
wasMapped = subview->flags.mapped;
|
||||
if (wasMapped) {
|
||||
W_UnmapView(subview);
|
||||
}
|
||||
|
||||
W_ReparentView(subview, sPtr->view);
|
||||
|
||||
#if 0
|
||||
if (sPtr->resizeSubviewsProc && subviewCount(sPtr)>1) {
|
||||
(*sPtr->resizeSubviewsProc)(sPtr, sPtr->view->size.width,
|
||||
sPtr->view->size.height);
|
||||
/* check if there is free space for the new subview and
|
||||
* put the subview in it */
|
||||
} else {
|
||||
}
|
||||
#endif
|
||||
WMAdjustSplitViewSubviews(sPtr);
|
||||
|
||||
if (subviewCount(sPtr)==2)
|
||||
sPtr->flags.splitViewIsFull = 1;
|
||||
|
||||
if (wasMapped) {
|
||||
W_MapView(subview);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetSplitViewConstrainProc(WMSplitView *sPtr, WMSplitViewConstrainProc *proc)
|
||||
{
|
||||
sPtr->constrainProc = proc;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMAdjustSplitViewSubviews(WMSplitView *sPtr)
|
||||
{
|
||||
int theight = sPtr->view->size.height;
|
||||
int width = sPtr->view->size.width;
|
||||
int height;
|
||||
int y, count;
|
||||
W_View *view;
|
||||
|
||||
count = subviewCount(sPtr);
|
||||
|
||||
height = (theight - (count-1)*DIVIDER_THICKNESS)/count;
|
||||
|
||||
|
||||
view = sPtr->view->childrenList;
|
||||
if (view->self) {
|
||||
WMMoveWidget(view->self, 0, 0);
|
||||
WMResizeWidget(view->self, width, height);
|
||||
} else {
|
||||
W_MoveView(view, 0, 0);
|
||||
W_ResizeView(view, width, height);
|
||||
}
|
||||
|
||||
y = height + DIVIDER_THICKNESS;
|
||||
|
||||
for (view = view->nextSister; view != NULL; view = view->nextSister) {
|
||||
if (view->self) {
|
||||
WMMoveWidget(view->self, 0, y);
|
||||
WMResizeWidget(view->self, width, height);
|
||||
} else {
|
||||
W_MoveView(view, 0, y);
|
||||
W_ResizeView(view, width, height);
|
||||
}
|
||||
y += height + DIVIDER_THICKNESS;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
WMSetSplitViewResizeSubviewsProc(WMSplitView *sPtr,
|
||||
WMSplitViewResizeSubviewsProc *proc)
|
||||
{
|
||||
sPtr->resizeSubviewsProc = proc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
WMGetSplitViewDividerThickness(WMSplitView *sPtr)
|
||||
{
|
||||
return DIVIDER_THICKNESS;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintSplitView(SplitView *sPtr)
|
||||
{
|
||||
W_Screen *scr = sPtr->view->screen;
|
||||
int y, x;
|
||||
W_View *ptr;
|
||||
WMPixmap *dimple = scr->scrollerDimple;
|
||||
|
||||
XClearWindow(scr->display, sPtr->view->window);
|
||||
|
||||
x = (sPtr->view->size.width - dimple->width)/2;
|
||||
|
||||
ptr = sPtr->view->childrenList;
|
||||
|
||||
y = ptr->size.height;
|
||||
XSetClipMask(scr->display, scr->clipGC, dimple->mask);
|
||||
while (ptr->nextSister) {
|
||||
y += (DIVIDER_THICKNESS - dimple->width)/2;
|
||||
|
||||
XSetClipOrigin(scr->display, scr->clipGC, x, y);
|
||||
XCopyArea(scr->display, dimple->pixmap, sPtr->view->window,
|
||||
scr->clipGC, 0, 0, dimple->width, dimple->height, x, y);
|
||||
|
||||
y += ptr->size.height;
|
||||
|
||||
ptr = ptr->nextSister;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
SplitView *sPtr = (SplitView*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_SplitView);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintSplitView(sPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroySplitView(sPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dragDivider(SplitView *sPtr, int clickY)
|
||||
{
|
||||
int divider;
|
||||
WMView *view, *view1=NULL, *view2=NULL;
|
||||
int y;
|
||||
int ofsY;
|
||||
int done;
|
||||
int dragging;
|
||||
int minCoord;
|
||||
int maxCoord;
|
||||
XEvent ev;
|
||||
WMScreen *scr = sPtr->view->screen;
|
||||
|
||||
view = sPtr->view->childrenList;
|
||||
divider = 0;
|
||||
ofsY = 0;
|
||||
y = 0;
|
||||
done = 0;
|
||||
while (view) {
|
||||
y += view->size.height+DIVIDER_THICKNESS;
|
||||
if (clickY < y) {
|
||||
/* offset from point where use clicked and the top of the
|
||||
* divider */
|
||||
ofsY = clickY - y + DIVIDER_THICKNESS;
|
||||
view1 = view;
|
||||
view2 = view->nextSister;
|
||||
/* can't be NULL. It would mean the divider is at the bottom */
|
||||
assert(view2!=NULL);
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
view = view->nextSister;
|
||||
divider++;
|
||||
}
|
||||
assert(done);
|
||||
|
||||
minCoord = view1->pos.y;
|
||||
maxCoord = view2->pos.y+view2->size.height-DIVIDER_THICKNESS;
|
||||
|
||||
if (sPtr->constrainProc)
|
||||
(*sPtr->constrainProc)(sPtr, divider, &minCoord, &maxCoord);
|
||||
|
||||
done = 0;
|
||||
dragging = 0;
|
||||
while (!done) {
|
||||
WMMaskEvent(scr->display, ButtonMotionMask|ButtonReleaseMask
|
||||
|ExposureMask, &ev);
|
||||
|
||||
switch (ev.type) {
|
||||
case ButtonRelease:
|
||||
done = 1;
|
||||
if (dragging) {
|
||||
XFillRectangle(scr->display, sPtr->view->window, scr->ixorGC,
|
||||
0, y, sPtr->view->size.width,DIVIDER_THICKNESS);
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
if (dragging) {
|
||||
XFillRectangle(scr->display, sPtr->view->window, scr->ixorGC,
|
||||
0, y, sPtr->view->size.width,DIVIDER_THICKNESS);
|
||||
}
|
||||
if (ev.xmotion.y-ofsY < minCoord)
|
||||
y = minCoord;
|
||||
else if (ev.xmotion.y-ofsY > maxCoord)
|
||||
y = maxCoord;
|
||||
else
|
||||
y = ev.xmotion.y-ofsY;
|
||||
XFillRectangle(scr->display, sPtr->view->window, scr->ixorGC,
|
||||
0, y, sPtr->view->size.width, DIVIDER_THICKNESS);
|
||||
dragging = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
WMHandleEvent(&ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dragging) {
|
||||
int theight;
|
||||
|
||||
theight = view1->size.height + view2->size.height + DIVIDER_THICKNESS;
|
||||
|
||||
WMResizeWidget(view1->self, sPtr->view->size.width, y - view1->pos.y);
|
||||
|
||||
WMResizeWidget(view2->self, sPtr->view->size.width,
|
||||
theight - view1->size.height - DIVIDER_THICKNESS);
|
||||
WMMoveWidget(view2->self, 0,
|
||||
view1->pos.y+view1->size.height+DIVIDER_THICKNESS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
|
||||
CHECK_CLASS(data, WC_SplitView);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case ButtonPress:
|
||||
if (event->xbutton.button == Button1)
|
||||
dragDivider(data, event->xbutton.y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroySplitView(SplitView *sPtr)
|
||||
{
|
||||
WMRemoveNotificationObserver(sPtr);
|
||||
|
||||
free(sPtr);
|
||||
}
|
||||
|
||||
445
WINGs/wtest.c
Normal file
445
WINGs/wtest.c
Normal file
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
* WINGs test application
|
||||
*/
|
||||
|
||||
#include "WINGs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* You need to define this function to link any program to WINGs.
|
||||
* This will be called when the application will be terminated because
|
||||
* on a fatal error.
|
||||
*/
|
||||
void
|
||||
wAbort()
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Display *dpy;
|
||||
|
||||
int windowCount = 0;
|
||||
|
||||
void
|
||||
closeAction(WMWidget *self, void *data)
|
||||
{
|
||||
WMDestroyWidget(self);
|
||||
windowCount--;
|
||||
if (windowCount < 1)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testOpenFilePanel(WMScreen *scr)
|
||||
{
|
||||
WMOpenPanel *panel;
|
||||
|
||||
windowCount++;
|
||||
|
||||
/* get the shared Open File panel */
|
||||
panel = WMGetOpenPanel(scr);
|
||||
|
||||
WMRunModalOpenPanelForDirectory(panel, NULL, "/usr/local", NULL, NULL);
|
||||
|
||||
/* free the panel to save some memory. Not needed otherwise. */
|
||||
WMFreeFilePanel(panel);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testFontPanel(WMScreen *scr)
|
||||
{
|
||||
WMFontPanel *panel;
|
||||
|
||||
windowCount++;
|
||||
|
||||
panel = WMGetFontPanel(scr);
|
||||
|
||||
WMShowFontPanel(panel);
|
||||
|
||||
/* WMFreeFontPanel(panel);*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
testList(WMScreen *scr)
|
||||
{
|
||||
WMWindow *win;
|
||||
WMList *list;
|
||||
char text[100];
|
||||
int i;
|
||||
|
||||
windowCount++;
|
||||
|
||||
win = WMCreateWindow(scr, "testList");
|
||||
WMSetWindowTitle(win, "List");
|
||||
WMSetWindowCloseAction(win, closeAction, NULL);
|
||||
|
||||
list = WMCreateList(win);
|
||||
for (i=0; i<50; i++) {
|
||||
sprintf(text, "Item %i", i);
|
||||
WMAddListItem(list, text);
|
||||
}
|
||||
WMRealizeWidget(win);
|
||||
WMMapSubwidgets(win);
|
||||
WMMapWidget(win);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testGradientButtons(WMScreen *scr)
|
||||
{
|
||||
WMWindow *win;
|
||||
WMButton *btn;
|
||||
WMPixmap *pix1, *pix2;
|
||||
RImage *back;
|
||||
RColor light, dark;
|
||||
WMColor *color;
|
||||
|
||||
windowCount++;
|
||||
|
||||
/* creates the top-level window */
|
||||
win = WMCreateWindow(scr, "testGradientButtons");
|
||||
WMSetWindowTitle(win, "Gradiented Button Demo");
|
||||
WMResizeWidget(win, 300, 200);
|
||||
|
||||
light.red = 0x90;
|
||||
light.green = 0x85;
|
||||
light.blue = 0x90;
|
||||
dark.red = 0x35;
|
||||
dark.green = 0x30;
|
||||
dark.blue = 0x35;
|
||||
|
||||
color = WMCreateRGBColor(scr, 0x5900, 0x5100, 0x5900, True);
|
||||
WMSetWidgetBackgroundColor(win, color);
|
||||
WMReleaseColor(color);
|
||||
|
||||
back = RRenderGradient(60, 24, &dark, &light, RGRD_DIAGONAL);
|
||||
RBevelImage(back, RBEV_RAISED2);
|
||||
pix1 = WMCreatePixmapFromRImage(scr, back, 0);
|
||||
RDestroyImage(back);
|
||||
|
||||
back = RRenderGradient(60, 24, &dark, &light, RGRD_DIAGONAL);
|
||||
RBevelImage(back, RBEV_SUNKEN);
|
||||
pix2 = WMCreatePixmapFromRImage(scr, back, 0);
|
||||
RDestroyImage(back);
|
||||
|
||||
btn = WMCreateButton(win, WBTMomentaryChange);
|
||||
WMResizeWidget(btn, 60, 24);
|
||||
WMMoveWidget(btn, 20, 100);
|
||||
WMSetButtonBordered(btn, False);
|
||||
WMSetButtonImagePosition(btn, WIPOverlaps);
|
||||
WMSetButtonImage(btn, pix1);
|
||||
WMSetButtonAltImage(btn, pix2);
|
||||
WMSetButtonText(btn, "Cool");
|
||||
|
||||
btn = WMCreateButton(win, WBTMomentaryChange);
|
||||
WMResizeWidget(btn, 60, 24);
|
||||
WMMoveWidget(btn, 90, 100);
|
||||
WMSetButtonBordered(btn, False);
|
||||
WMSetButtonImagePosition(btn, WIPOverlaps);
|
||||
WMSetButtonImage(btn, pix1);
|
||||
WMSetButtonAltImage(btn, pix2);
|
||||
WMSetButtonText(btn, "Button");
|
||||
|
||||
btn = WMCreateButton(win, WBTMomentaryChange);
|
||||
WMResizeWidget(btn, 60, 24);
|
||||
WMMoveWidget(btn, 160, 100);
|
||||
WMSetButtonBordered(btn, False);
|
||||
WMSetButtonImagePosition(btn, WIPOverlaps);
|
||||
WMSetButtonImage(btn, pix1);
|
||||
WMSetButtonAltImage(btn, pix2);
|
||||
WMSetButtonText(btn, "Test");
|
||||
|
||||
WMRealizeWidget(win);
|
||||
WMMapSubwidgets(win);
|
||||
WMMapWidget(win);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testScrollView(WMScreen *scr)
|
||||
{
|
||||
WMWindow *win;
|
||||
WMScrollView *sview;
|
||||
WMFrame *f;
|
||||
WMLabel *l;
|
||||
char buffer[128];
|
||||
int i;
|
||||
|
||||
windowCount++;
|
||||
|
||||
/* creates the top-level window */
|
||||
win = WMCreateWindow(scr, "testScroll");
|
||||
WMSetWindowTitle(win, "Scrollable View");
|
||||
|
||||
WMSetWindowCloseAction(win, closeAction, NULL);
|
||||
|
||||
/* set the window size */
|
||||
WMResizeWidget(win, 300, 300);
|
||||
|
||||
/* creates a scrollable view inside the top-level window */
|
||||
sview = WMCreateScrollView(win);
|
||||
WMResizeWidget(sview, 200, 200);
|
||||
WMMoveWidget(sview, 30, 30);
|
||||
WMSetScrollViewRelief(sview, WRSunken);
|
||||
WMSetScrollViewHasVerticalScroller(sview, True);
|
||||
WMSetScrollViewHasHorizontalScroller(sview, True);
|
||||
|
||||
/* create a frame with a bunch of labels */
|
||||
f = WMCreateFrame(win);
|
||||
WMResizeWidget(f, 400, 400);
|
||||
WMSetFrameRelief(f, WRFlat);
|
||||
|
||||
for (i=0; i<20; i++) {
|
||||
l = WMCreateLabel(f);
|
||||
WMResizeWidget(l, 50, 18);
|
||||
WMMoveWidget(l, 10, 20*i);
|
||||
sprintf(buffer, "Label %i", i);
|
||||
WMSetLabelText(l, buffer);
|
||||
WMSetLabelRelief(l, WRSimple);
|
||||
}
|
||||
WMMapSubwidgets(f);
|
||||
WMMapWidget(f);
|
||||
|
||||
WMSetScrollViewContentView(sview, WMWidgetView(f));
|
||||
|
||||
/* make the windows of the widgets be actually created */
|
||||
WMRealizeWidget(win);
|
||||
|
||||
/* Map all child widgets of the top-level be mapped.
|
||||
* You must call this for each container widget (like frames),
|
||||
* even if they are childs of the top-level window.
|
||||
*/
|
||||
WMMapSubwidgets(win);
|
||||
|
||||
/* map the top-level window */
|
||||
WMMapWidget(win);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testColorWell(WMScreen *scr)
|
||||
{
|
||||
WMWindow *win;
|
||||
WMColorWell *well1, *well2;
|
||||
|
||||
windowCount++;
|
||||
|
||||
win = WMCreateWindow(scr, "testColor");
|
||||
WMResizeWidget(win, 300, 300);
|
||||
|
||||
WMSetWindowCloseAction(win, closeAction, NULL);
|
||||
|
||||
well1 = WMCreateColorWell(win);
|
||||
WMResizeWidget(well1, 60, 40);
|
||||
WMMoveWidget(well1, 100, 100);
|
||||
WMSetColorWellColor(well1, WMCreateRGBColor(scr, 0x8888, 0, 0x1111, True));
|
||||
well2 = WMCreateColorWell(win);
|
||||
WMResizeWidget(well2, 60, 40);
|
||||
WMMoveWidget(well2, 200, 100);
|
||||
WMSetColorWellColor(well2, WMCreateRGBColor(scr, 0, 0, 0x8888, True));
|
||||
|
||||
WMRealizeWidget(win);
|
||||
WMMapSubwidgets(win);
|
||||
WMMapWidget(win);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testSlider(WMScreen *scr)
|
||||
{
|
||||
WMWindow *win;
|
||||
WMSlider *s;
|
||||
|
||||
windowCount++;
|
||||
|
||||
win = WMCreateWindow(scr, "testSlider");
|
||||
WMResizeWidget(win, 300, 300);
|
||||
WMSetWindowTitle(win, "Sliders");
|
||||
|
||||
WMSetWindowCloseAction(win, closeAction, NULL);
|
||||
|
||||
s = WMCreateSlider(win);
|
||||
WMResizeWidget(s, 16, 100);
|
||||
WMMoveWidget(s, 100, 100);
|
||||
|
||||
s = WMCreateSlider(win);
|
||||
WMResizeWidget(s, 100, 16);
|
||||
WMMoveWidget(s, 100, 10);
|
||||
|
||||
WMRealizeWidget(win);
|
||||
WMMapSubwidgets(win);
|
||||
WMMapWidget(win);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
testText(WMScreen *scr)
|
||||
{
|
||||
WMWindow *win;
|
||||
WMSimpleText *text;
|
||||
|
||||
windowCount++;
|
||||
|
||||
win = WMCreateWindow(scr, "testText");
|
||||
WMResizeWidget(win, 300, 300);
|
||||
WMSetWindowTitle(win, "Text");
|
||||
|
||||
WMSetWindowCloseAction(win, closeAction, NULL);
|
||||
|
||||
text = WMCreateSimpleText(win);
|
||||
WMResizeWidget(text, 280, 280);
|
||||
WMMoveWidget(text, 10, 10);
|
||||
|
||||
WMRealizeWidget(win);
|
||||
WMMapSubwidgets(win);
|
||||
WMMapWidget(win);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
testTextField(WMScreen *scr)
|
||||
{
|
||||
WMWindow *win;
|
||||
WMTextField *field, *field2;
|
||||
|
||||
windowCount++;
|
||||
|
||||
win = WMCreateWindow(scr, "testText");
|
||||
WMResizeWidget(win, 400, 300);
|
||||
|
||||
WMSetWindowCloseAction(win, closeAction, NULL);
|
||||
|
||||
field = WMCreateTextField(win);
|
||||
WMResizeWidget(field, 200, 20);
|
||||
WMMoveWidget(field, 20, 20);
|
||||
|
||||
field2 = WMCreateTextField(win);
|
||||
WMResizeWidget(field2, 200, 20);
|
||||
WMMoveWidget(field2, 20, 50);
|
||||
WMSetTextFieldAlignment(field2, WARight);
|
||||
|
||||
WMRealizeWidget(win);
|
||||
WMMapSubwidgets(win);
|
||||
WMMapWidget(win);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
testPullDown(WMScreen *scr)
|
||||
{
|
||||
WMWindow *win;
|
||||
WMPopUpButton *pop, *pop2;
|
||||
|
||||
windowCount++;
|
||||
|
||||
win = WMCreateWindow(scr, "pullDown");
|
||||
WMResizeWidget(win, 400, 300);
|
||||
|
||||
WMSetWindowCloseAction(win, closeAction, NULL);
|
||||
|
||||
pop = WMCreatePopUpButton(win);
|
||||
WMResizeWidget(pop, 100, 20);
|
||||
WMMoveWidget(pop, 50, 60);
|
||||
WMSetPopUpButtonPullsDown(pop, True);
|
||||
WMSetPopUpButtonText(pop, "Commands");
|
||||
WMAddPopUpButtonItem(pop, "Add");
|
||||
WMAddPopUpButtonItem(pop, "Remove");
|
||||
WMAddPopUpButtonItem(pop, "Check");
|
||||
WMAddPopUpButtonItem(pop, "Eat");
|
||||
|
||||
pop2 = WMCreatePopUpButton(win);
|
||||
WMResizeWidget(pop2, 100, 20);
|
||||
WMMoveWidget(pop2, 200, 60);
|
||||
WMSetPopUpButtonText(pop2, "Select");
|
||||
WMAddPopUpButtonItem(pop2, "Apples");
|
||||
WMAddPopUpButtonItem(pop2, "Bananas");
|
||||
WMAddPopUpButtonItem(pop2, "Strawberries");
|
||||
WMAddPopUpButtonItem(pop2, "Blueberries");
|
||||
|
||||
WMRealizeWidget(win);
|
||||
WMMapSubwidgets(win);
|
||||
WMMapWidget(win);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "WUtil.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
WMScreen *scr;
|
||||
WMPixmap *pixmap;
|
||||
|
||||
/* Initialize the application */
|
||||
WMInitializeApplication("Test", &argc, argv);
|
||||
|
||||
/*
|
||||
* Open connection to the X display.
|
||||
*/
|
||||
dpy = XOpenDisplay("");
|
||||
|
||||
if (!dpy) {
|
||||
puts("could not open display");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* This is used to disable buffering of X protocol requests.
|
||||
* Do NOT use it unless when debugging. It will cause a major
|
||||
* slowdown in your application
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
XSynchronize(dpy, True);
|
||||
#endif
|
||||
/*
|
||||
* Create screen descriptor.
|
||||
*/
|
||||
scr = WMCreateScreen(dpy, DefaultScreen(dpy));
|
||||
|
||||
/*
|
||||
* Loads the logo of the application.
|
||||
*/
|
||||
pixmap = WMCreatePixmapFromFile(scr, "logo.xpm");
|
||||
|
||||
/*
|
||||
* Makes the logo be used in standard dialog panels.
|
||||
*/
|
||||
WMSetApplicationIconImage(scr, pixmap); WMReleasePixmap(pixmap);
|
||||
|
||||
/*
|
||||
* Do some test stuff.
|
||||
*
|
||||
* Put the testSomething() function you want to test here.
|
||||
*/
|
||||
#if 0
|
||||
testOpenFilePanel(scr);
|
||||
testFontPanel(scr);
|
||||
testList(scr);
|
||||
testGradientButtons(scr);
|
||||
testScrollView(scr);
|
||||
testColorWell(scr);
|
||||
testSlider(scr);
|
||||
testTextField(scr);
|
||||
testPullDown(scr);
|
||||
#endif
|
||||
/*
|
||||
* The main event loop.
|
||||
*
|
||||
*/
|
||||
WMScreenMainLoop(scr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
880
WINGs/wtextfield.c
Normal file
880
WINGs/wtextfield.c
Normal file
@@ -0,0 +1,880 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define CURSOR_BLINK_ON_DELAY 600
|
||||
#define CURSOR_BLINK_OFF_DELAY 300
|
||||
|
||||
|
||||
char *WMTextDidChangeNotification = "WMTextDidChangeNotification";
|
||||
char *WMTextDidBeginEditingNotification = "WMTextDidBeginEditingNotification";
|
||||
char *WMTextDidEndEditingNotification = "WMTextDidEndEditingNotification";
|
||||
|
||||
|
||||
typedef struct W_TextField {
|
||||
W_Class widgetClass;
|
||||
W_View *view;
|
||||
|
||||
struct W_TextField *nextField; /* next textfield in the chain */
|
||||
struct W_TextField *prevField;
|
||||
|
||||
char *text;
|
||||
int textLen; /* size of text */
|
||||
int bufferSize; /* memory allocated for text */
|
||||
|
||||
int viewPosition; /* position of text being shown */
|
||||
|
||||
int cursorPosition; /* position of the insertion cursor */
|
||||
|
||||
short usableWidth;
|
||||
short offsetWidth; /* offset of text from border */
|
||||
|
||||
#if 0
|
||||
WMHandlerID timerID; /* for cursor blinking */
|
||||
#endif
|
||||
struct {
|
||||
WMAlignment alignment:2;
|
||||
|
||||
unsigned int bordered:1;
|
||||
|
||||
unsigned int enabled:1;
|
||||
|
||||
unsigned int focused:1;
|
||||
|
||||
unsigned int cursorOn:1;
|
||||
|
||||
unsigned int secure:1; /* password entry style */
|
||||
|
||||
/**/
|
||||
unsigned int notIllegalMovement:1;
|
||||
} flags;
|
||||
} TextField;
|
||||
|
||||
|
||||
#define MIN_TEXT_BUFFER 2
|
||||
#define TEXT_BUFFER_INCR 8
|
||||
|
||||
|
||||
#define WM_EMACSKEYMASK ControlMask
|
||||
|
||||
#define WM_EMACSKEY_LEFT XK_b
|
||||
#define WM_EMACSKEY_RIGHT XK_f
|
||||
#define WM_EMACSKEY_HOME XK_a
|
||||
#define WM_EMACSKEY_END XK_e
|
||||
#define WM_EMACSKEY_BS XK_h
|
||||
#define WM_EMACSKEY_DEL XK_d
|
||||
|
||||
|
||||
|
||||
#define DEFAULT_WIDTH 60
|
||||
#define DEFAULT_HEIGHT 20
|
||||
#define DEFAULT_BORDERED True
|
||||
#define DEFAULT_ALIGNMENT WALeft
|
||||
|
||||
|
||||
|
||||
static void destroyTextField(TextField *tPtr);
|
||||
static void paintTextField(TextField *tPtr);
|
||||
|
||||
static void handleEvents(XEvent *event, void *data);
|
||||
static void handleTextFieldActionEvents(XEvent *event, void *data);
|
||||
static void resizeTextField();
|
||||
|
||||
struct W_ViewProcedureTable _TextFieldViewProcedures = {
|
||||
NULL,
|
||||
resizeTextField,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
#define TEXT_WIDTH(tPtr, start) (WMWidthOfString((tPtr)->view->screen->normalFont, \
|
||||
&((tPtr)->text[(start)]), (tPtr)->textLen - (start) + 1))
|
||||
|
||||
#define TEXT_WIDTH2(tPtr, start, end) (WMWidthOfString((tPtr)->view->screen->normalFont, \
|
||||
&((tPtr)->text[(start)]), (end) - (start) + 1))
|
||||
|
||||
|
||||
static void
|
||||
memmv(char *dest, char *src, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dest > src) {
|
||||
for (i=size-1; i>=0; i--) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
} else if (dest < src) {
|
||||
for (i=0; i<size; i++) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
incrToFit(TextField *tPtr)
|
||||
{
|
||||
int vp = tPtr->viewPosition;
|
||||
|
||||
while (TEXT_WIDTH(tPtr, tPtr->viewPosition) > tPtr->usableWidth) {
|
||||
tPtr->viewPosition++;
|
||||
}
|
||||
return vp!=tPtr->viewPosition;
|
||||
}
|
||||
|
||||
static int
|
||||
incrToFit2(TextField *tPtr)
|
||||
{
|
||||
int vp = tPtr->viewPosition;
|
||||
while (TEXT_WIDTH2(tPtr, tPtr->viewPosition, tPtr->cursorPosition)
|
||||
>= tPtr->usableWidth)
|
||||
tPtr->viewPosition++;
|
||||
|
||||
|
||||
return vp!=tPtr->viewPosition;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
decrToFit(TextField *tPtr)
|
||||
{
|
||||
while (TEXT_WIDTH(tPtr, tPtr->viewPosition-1) < tPtr->usableWidth
|
||||
&& tPtr->viewPosition>0)
|
||||
tPtr->viewPosition--;
|
||||
}
|
||||
|
||||
#undef TEXT_WIDTH
|
||||
#undef TEXT_WIDTH2
|
||||
|
||||
|
||||
WMTextField*
|
||||
WMCreateTextField(WMWidget *parent)
|
||||
{
|
||||
TextField *tPtr;
|
||||
|
||||
|
||||
tPtr = wmalloc(sizeof(TextField));
|
||||
memset(tPtr, 0, sizeof(TextField));
|
||||
|
||||
tPtr->widgetClass = WC_TextField;
|
||||
|
||||
tPtr->view = W_CreateView(W_VIEW(parent));
|
||||
if (!tPtr->view) {
|
||||
free(tPtr);
|
||||
return NULL;
|
||||
}
|
||||
tPtr->view->self = tPtr;
|
||||
|
||||
tPtr->view->attribFlags |= CWCursor;
|
||||
tPtr->view->attribs.cursor = tPtr->view->screen->textCursor;
|
||||
|
||||
W_SetViewBackgroundColor(tPtr->view, tPtr->view->screen->white);
|
||||
|
||||
tPtr->text = wmalloc(MIN_TEXT_BUFFER);
|
||||
tPtr->text[0] = 0;
|
||||
tPtr->textLen = 0;
|
||||
tPtr->bufferSize = MIN_TEXT_BUFFER;
|
||||
|
||||
tPtr->flags.enabled = 1;
|
||||
|
||||
WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask
|
||||
|FocusChangeMask, handleEvents, tPtr);
|
||||
|
||||
W_ResizeView(tPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
WMSetTextFieldBordered(tPtr, DEFAULT_BORDERED);
|
||||
tPtr->flags.alignment = DEFAULT_ALIGNMENT;
|
||||
tPtr->offsetWidth = (tPtr->view->size.height
|
||||
- tPtr->view->screen->normalFont->height)/2;
|
||||
|
||||
WMCreateEventHandler(tPtr->view, EnterWindowMask|LeaveWindowMask
|
||||
|ButtonPressMask|KeyPressMask|Button1MotionMask,
|
||||
handleTextFieldActionEvents, tPtr);
|
||||
|
||||
tPtr->flags.cursorOn = 1;
|
||||
|
||||
return tPtr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMInsertTextFieldText(WMTextField *tPtr, char *text, int position)
|
||||
{
|
||||
int len;
|
||||
|
||||
CHECK_CLASS(tPtr, WC_TextField);
|
||||
|
||||
if (!text)
|
||||
return;
|
||||
|
||||
len = strlen(text);
|
||||
|
||||
/* check if buffer will hold the text */
|
||||
if (len + tPtr->textLen >= tPtr->bufferSize) {
|
||||
tPtr->bufferSize = tPtr->textLen + len + TEXT_BUFFER_INCR;
|
||||
tPtr->text = realloc(tPtr->text, tPtr->bufferSize);
|
||||
}
|
||||
|
||||
if (position < 0 || position >= tPtr->textLen) {
|
||||
/* append the text at the end */
|
||||
strcat(tPtr->text, text);
|
||||
|
||||
incrToFit(tPtr);
|
||||
|
||||
tPtr->textLen += len;
|
||||
tPtr->cursorPosition += len;
|
||||
} else {
|
||||
/* insert text at position */
|
||||
memmv(&(tPtr->text[position+len]), &(tPtr->text[position]),
|
||||
tPtr->textLen-position+1);
|
||||
|
||||
memcpy(&(tPtr->text[position]), text, len);
|
||||
|
||||
tPtr->textLen += len;
|
||||
if (position >= tPtr->cursorPosition) {
|
||||
tPtr->cursorPosition += len;
|
||||
incrToFit2(tPtr);
|
||||
} else {
|
||||
incrToFit(tPtr);
|
||||
}
|
||||
}
|
||||
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMDeleteTextFieldRange(WMTextField *tPtr, WMRange range)
|
||||
{
|
||||
CHECK_CLASS(tPtr, WC_TextField);
|
||||
|
||||
if (range.position >= tPtr->textLen)
|
||||
return;
|
||||
|
||||
if (range.count < 1) {
|
||||
if (range.position < 0)
|
||||
range.position = 0;
|
||||
tPtr->text[range.position] = 0;
|
||||
tPtr->textLen = range.position;
|
||||
|
||||
tPtr->cursorPosition = 0;
|
||||
tPtr->viewPosition = 0;
|
||||
} else {
|
||||
if (range.position + range.count > tPtr->textLen)
|
||||
range.count = tPtr->textLen - range.position;
|
||||
memmv(&(tPtr->text[range.position]), &(tPtr->text[range.position+range.count]),
|
||||
tPtr->textLen - (range.position+range.count) + 1);
|
||||
tPtr->textLen -= range.count;
|
||||
|
||||
if (tPtr->cursorPosition > range.position)
|
||||
tPtr->cursorPosition -= range.count;
|
||||
|
||||
decrToFit(tPtr);
|
||||
}
|
||||
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char*
|
||||
WMGetTextFieldText(WMTextField *tPtr)
|
||||
{
|
||||
CHECK_CLASS(tPtr, WC_TextField);
|
||||
|
||||
return wstrdup(tPtr->text);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetTextFieldText(WMTextField *tPtr, char *text)
|
||||
{
|
||||
if (text==NULL) {
|
||||
tPtr->text[0] = 0;
|
||||
tPtr->textLen = 0;
|
||||
} else {
|
||||
tPtr->textLen = strlen(text);
|
||||
|
||||
if (tPtr->textLen >= tPtr->bufferSize) {
|
||||
tPtr->bufferSize = tPtr->textLen + TEXT_BUFFER_INCR;
|
||||
tPtr->text = realloc(tPtr->text, tPtr->bufferSize);
|
||||
}
|
||||
strcpy(tPtr->text, text);
|
||||
}
|
||||
if (tPtr->textLen < tPtr->cursorPosition)
|
||||
tPtr->cursorPosition = tPtr->textLen;
|
||||
|
||||
if (tPtr->view->flags.realized)
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetTextFieldAlignment(WMTextField *tPtr, WMAlignment alignment)
|
||||
{
|
||||
tPtr->flags.alignment = alignment;
|
||||
if (alignment!=WALeft) {
|
||||
wwarning("only left alignment is supported in textfields");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tPtr->view->flags.realized) {
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetTextFieldBordered(WMTextField *tPtr, Bool bordered)
|
||||
{
|
||||
tPtr->flags.bordered = bordered;
|
||||
|
||||
if (tPtr->view->flags.realized) {
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetTextFieldSecure(WMTextField *tPtr, Bool flag)
|
||||
{
|
||||
tPtr->flags.secure = flag;
|
||||
|
||||
if (tPtr->view->flags.realized) {
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetTextFieldEnabled(WMTextField *tPtr, Bool flag)
|
||||
{
|
||||
tPtr->flags.enabled = flag;
|
||||
|
||||
if (tPtr->view->flags.realized) {
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resizeTextField(WMTextField *tPtr, unsigned int width, unsigned int height)
|
||||
{
|
||||
W_ResizeView(tPtr->view, width, height);
|
||||
|
||||
tPtr->offsetWidth = (tPtr->view->size.height
|
||||
- tPtr->view->screen->normalFont->height)/2;
|
||||
|
||||
tPtr->usableWidth = tPtr->view->size.width - 2*tPtr->offsetWidth;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintCursor(TextField *tPtr)
|
||||
{
|
||||
int cx;
|
||||
WMScreen *screen = tPtr->view->screen;
|
||||
int textWidth;
|
||||
|
||||
cx = WMWidthOfString(screen->normalFont,
|
||||
&(tPtr->text[tPtr->viewPosition]),
|
||||
tPtr->cursorPosition-tPtr->viewPosition);
|
||||
|
||||
switch (tPtr->flags.alignment) {
|
||||
case WARight:
|
||||
textWidth = WMWidthOfString(screen->normalFont, tPtr->text,
|
||||
tPtr->textLen);
|
||||
if (textWidth < tPtr->usableWidth)
|
||||
cx += tPtr->offsetWidth + tPtr->usableWidth - textWidth;
|
||||
else
|
||||
cx += tPtr->offsetWidth;
|
||||
break;
|
||||
case WALeft:
|
||||
cx += tPtr->offsetWidth;
|
||||
break;
|
||||
case WACenter:
|
||||
textWidth = WMWidthOfString(screen->normalFont, tPtr->text,
|
||||
tPtr->textLen);
|
||||
if (textWidth < tPtr->usableWidth)
|
||||
cx += tPtr->offsetWidth + (tPtr->usableWidth-textWidth)/2;
|
||||
else
|
||||
cx += tPtr->offsetWidth;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
XDrawRectangle(screen->display, tPtr->view->window, screen->xorGC,
|
||||
cx, tPtr->offsetWidth, 1,
|
||||
tPtr->view->size.height - 2*tPtr->offsetWidth - 1);
|
||||
*/
|
||||
XDrawLine(screen->display, tPtr->view->window, screen->xorGC,
|
||||
cx, tPtr->offsetWidth, cx,
|
||||
tPtr->view->size.height - tPtr->offsetWidth - 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
drawRelief(WMView *view)
|
||||
{
|
||||
WMScreen *scr = view->screen;
|
||||
Display *dpy = scr->display;
|
||||
GC wgc;
|
||||
GC lgc;
|
||||
GC dgc;
|
||||
int width = view->size.width;
|
||||
int height = view->size.height;
|
||||
|
||||
wgc = W_GC(scr->white);
|
||||
dgc = W_GC(scr->darkGray);
|
||||
lgc = W_GC(scr->gray);
|
||||
|
||||
/* top left */
|
||||
XDrawLine(dpy, view->window, dgc, 0, 0, width-1, 0);
|
||||
XDrawLine(dpy, view->window, dgc, 0, 1, width-2, 1);
|
||||
|
||||
XDrawLine(dpy, view->window, dgc, 0, 0, 0, height-2);
|
||||
XDrawLine(dpy, view->window, dgc, 1, 0, 1, height-3);
|
||||
|
||||
/* bottom right */
|
||||
XDrawLine(dpy, view->window, wgc, 0, height-1, width-1, height-1);
|
||||
XDrawLine(dpy, view->window, lgc, 1, height-2, width-2, height-2);
|
||||
|
||||
XDrawLine(dpy, view->window, wgc, width-1, 0, width-1, height-1);
|
||||
XDrawLine(dpy, view->window, lgc, width-2, 1, width-2, height-3);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
paintTextField(TextField *tPtr)
|
||||
{
|
||||
W_Screen *screen = tPtr->view->screen;
|
||||
W_View *view = tPtr->view;
|
||||
int tx, ty, tw, th;
|
||||
int bd;
|
||||
int totalWidth;
|
||||
|
||||
|
||||
if (!view->flags.realized || !view->flags.mapped)
|
||||
return;
|
||||
|
||||
if (!tPtr->flags.bordered) {
|
||||
bd = 0;
|
||||
} else {
|
||||
bd = 2;
|
||||
}
|
||||
|
||||
totalWidth = tPtr->view->size.width - 2*bd;
|
||||
|
||||
if (tPtr->textLen > 0) {
|
||||
tw = WMWidthOfString(screen->normalFont,
|
||||
&(tPtr->text[tPtr->viewPosition]),
|
||||
tPtr->textLen - tPtr->viewPosition);
|
||||
|
||||
th = screen->normalFont->height;
|
||||
|
||||
ty = tPtr->offsetWidth;
|
||||
switch (tPtr->flags.alignment) {
|
||||
case WALeft:
|
||||
tx = tPtr->offsetWidth;
|
||||
if (tw < tPtr->usableWidth)
|
||||
XClearArea(screen->display, view->window, bd+tw, bd,
|
||||
totalWidth-tw, view->size.height-2*bd,
|
||||
False);
|
||||
break;
|
||||
|
||||
case WACenter:
|
||||
tx = tPtr->offsetWidth + (tPtr->usableWidth - tw) / 2;
|
||||
if (tw < tPtr->usableWidth)
|
||||
XClearArea(screen->display, view->window, bd, bd,
|
||||
totalWidth, view->size.height-2*bd, False);
|
||||
break;
|
||||
|
||||
default:
|
||||
case WARight:
|
||||
tx = tPtr->offsetWidth + tPtr->usableWidth - tw;
|
||||
if (tw < tPtr->usableWidth)
|
||||
XClearArea(screen->display, view->window, bd, bd,
|
||||
totalWidth-tw, view->size.height-2*bd, False);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tPtr->flags.secure) {
|
||||
if (!tPtr->flags.enabled)
|
||||
WMSetColorInGC(screen->darkGray, screen->textFieldGC);
|
||||
|
||||
WMDrawImageString(screen, view->window, screen->textFieldGC,
|
||||
screen->normalFont, tx, ty,
|
||||
&(tPtr->text[tPtr->viewPosition]),
|
||||
tPtr->textLen - tPtr->viewPosition);
|
||||
|
||||
if (!tPtr->flags.enabled)
|
||||
WMSetColorInGC(screen->black, screen->textFieldGC);
|
||||
}
|
||||
} else {
|
||||
XClearArea(screen->display, view->window, bd, bd, totalWidth,
|
||||
view->size.height - 2*bd, False);
|
||||
}
|
||||
|
||||
/* draw cursor */
|
||||
if (tPtr->flags.focused && tPtr->flags.enabled && tPtr->flags.cursorOn) {
|
||||
paintCursor(tPtr);
|
||||
}
|
||||
|
||||
/* draw relief */
|
||||
if (tPtr->flags.bordered) {
|
||||
drawRelief(view);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void
|
||||
blinkCursor(void *data)
|
||||
{
|
||||
TextField *tPtr = (TextField*)data;
|
||||
|
||||
if (tPtr->flags.cursorOn) {
|
||||
tPtr->timerID = WMAddTimerHandler(CURSOR_BLINK_OFF_DELAY, blinkCursor,
|
||||
data);
|
||||
} else {
|
||||
tPtr->timerID = WMAddTimerHandler(CURSOR_BLINK_ON_DELAY, blinkCursor,
|
||||
data);
|
||||
}
|
||||
paintCursor(tPtr);
|
||||
tPtr->flags.cursorOn = !tPtr->flags.cursorOn;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
TextField *tPtr = (TextField*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_TextField);
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case FocusIn:
|
||||
if (W_FocusedViewOfToplevel(W_TopLevelOfView(tPtr->view))!=tPtr->view)
|
||||
return;
|
||||
tPtr->flags.focused = 1;
|
||||
#if 0
|
||||
if (!tPtr->timerID) {
|
||||
tPtr->timerID = WMAddTimerHandler(CURSOR_BLINK_ON_DELAY,
|
||||
blinkCursor, tPtr);
|
||||
}
|
||||
#endif
|
||||
paintTextField(tPtr);
|
||||
|
||||
WMPostNotificationName(WMTextDidBeginEditingNotification, tPtr, NULL);
|
||||
|
||||
tPtr->flags.notIllegalMovement = 0;
|
||||
break;
|
||||
|
||||
case FocusOut:
|
||||
tPtr->flags.focused = 0;
|
||||
#if 0
|
||||
if (tPtr->timerID)
|
||||
WMDeleteTimerHandler(tPtr->timerID);
|
||||
tPtr->timerID = NULL;
|
||||
#endif
|
||||
|
||||
paintTextField(tPtr);
|
||||
if (!tPtr->flags.notIllegalMovement) {
|
||||
WMPostNotificationName(WMTextDidEndEditingNotification, tPtr,
|
||||
WMIllegalTextMovement);
|
||||
}
|
||||
break;
|
||||
|
||||
case Expose:
|
||||
if (event->xexpose.count!=0)
|
||||
break;
|
||||
paintTextField(tPtr);
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
destroyTextField(tPtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
|
||||
{
|
||||
char buffer[64];
|
||||
KeySym ksym;
|
||||
int count, refresh = 0;
|
||||
int control_pressed = 0;
|
||||
int changed;
|
||||
WMNotification *notif;
|
||||
WMScreen *scr = tPtr->view->screen;
|
||||
|
||||
changed = 0;
|
||||
|
||||
if (((XKeyEvent *) event)->state & WM_EMACSKEYMASK) {
|
||||
control_pressed = 1;
|
||||
}
|
||||
|
||||
count = XLookupString(&event->xkey, buffer, 63, &ksym, NULL);
|
||||
buffer[count] = '\0';
|
||||
|
||||
switch (ksym) {
|
||||
case XK_Tab:
|
||||
if (event->xkey.state & ShiftMask) {
|
||||
notif = WMCreateNotification(WMTextDidEndEditingNotification,
|
||||
tPtr, (void*)WMBacktabTextMovement);
|
||||
if (tPtr->view->prevFocusChain) {
|
||||
W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view),
|
||||
tPtr->view->prevFocusChain);
|
||||
tPtr->flags.notIllegalMovement = 1;
|
||||
}
|
||||
} else {
|
||||
notif = WMCreateNotification(WMTextDidEndEditingNotification,
|
||||
tPtr, (void*)WMTabTextMovement);
|
||||
if (tPtr->view->nextFocusChain) {
|
||||
W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view),
|
||||
tPtr->view->nextFocusChain);
|
||||
tPtr->flags.notIllegalMovement = 1;
|
||||
}
|
||||
}
|
||||
WMPostNotification(notif);
|
||||
WMReleaseNotification(notif);
|
||||
break;
|
||||
|
||||
case XK_Return:
|
||||
WMPostNotificationName(WMTextDidEndEditingNotification, tPtr,
|
||||
(void*)WMReturnTextMovement);
|
||||
break;
|
||||
|
||||
case WM_EMACSKEY_LEFT:
|
||||
if (!control_pressed) {
|
||||
goto normal_key;
|
||||
}
|
||||
case XK_KP_Left:
|
||||
case XK_Left:
|
||||
if (tPtr->cursorPosition > 0) {
|
||||
paintCursor(tPtr);
|
||||
tPtr->cursorPosition--;
|
||||
if (tPtr->cursorPosition < tPtr->viewPosition) {
|
||||
tPtr->viewPosition = tPtr->cursorPosition;
|
||||
refresh = 1;
|
||||
} else {
|
||||
paintCursor(tPtr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_EMACSKEY_RIGHT:
|
||||
if (!control_pressed) {
|
||||
goto normal_key;
|
||||
}
|
||||
case XK_KP_Right:
|
||||
case XK_Right:
|
||||
if (tPtr->cursorPosition < tPtr->textLen) {
|
||||
paintCursor(tPtr);
|
||||
tPtr->cursorPosition++;
|
||||
while (WMWidthOfString(scr->normalFont,
|
||||
&(tPtr->text[tPtr->viewPosition]),
|
||||
tPtr->cursorPosition-tPtr->viewPosition)
|
||||
> tPtr->usableWidth) {
|
||||
tPtr->viewPosition++;
|
||||
refresh = 1;
|
||||
}
|
||||
if (!refresh)
|
||||
paintCursor(tPtr);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_EMACSKEY_HOME:
|
||||
if (!control_pressed) {
|
||||
goto normal_key;
|
||||
}
|
||||
case XK_KP_Home:
|
||||
case XK_Home:
|
||||
if (tPtr->cursorPosition > 0) {
|
||||
paintCursor(tPtr);
|
||||
tPtr->cursorPosition = 0;
|
||||
if (tPtr->viewPosition > 0) {
|
||||
tPtr->viewPosition = 0;
|
||||
refresh = 1;
|
||||
} else {
|
||||
paintCursor(tPtr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_EMACSKEY_END:
|
||||
if (!control_pressed) {
|
||||
goto normal_key;
|
||||
}
|
||||
case XK_KP_End:
|
||||
case XK_End:
|
||||
if (tPtr->cursorPosition < tPtr->textLen) {
|
||||
paintCursor(tPtr);
|
||||
tPtr->cursorPosition = tPtr->textLen;
|
||||
tPtr->viewPosition = 0;
|
||||
while (WMWidthOfString(scr->normalFont,
|
||||
&(tPtr->text[tPtr->viewPosition]),
|
||||
tPtr->textLen-tPtr->viewPosition)
|
||||
>= tPtr->usableWidth) {
|
||||
tPtr->viewPosition++;
|
||||
refresh = 1;
|
||||
}
|
||||
if (!refresh)
|
||||
paintCursor(tPtr);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_EMACSKEY_BS:
|
||||
if (!control_pressed) {
|
||||
goto normal_key;
|
||||
}
|
||||
case XK_BackSpace:
|
||||
if (tPtr->cursorPosition > 0) {
|
||||
WMRange range;
|
||||
changed = 1;
|
||||
range.position = tPtr->cursorPosition-1;
|
||||
range.count = 1;
|
||||
WMDeleteTextFieldRange(tPtr, range);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_EMACSKEY_DEL:
|
||||
if (!control_pressed) {
|
||||
goto normal_key;
|
||||
}
|
||||
case XK_KP_Delete:
|
||||
case XK_Delete:
|
||||
if (tPtr->cursorPosition < tPtr->textLen) {
|
||||
WMRange range;
|
||||
changed = 1;
|
||||
range.position = tPtr->cursorPosition;
|
||||
range.count = 1;
|
||||
WMDeleteTextFieldRange(tPtr, range);
|
||||
}
|
||||
break;
|
||||
|
||||
normal_key:
|
||||
default:
|
||||
if (count > 0 && !iscntrl(buffer[0])) {
|
||||
changed = 1;
|
||||
WMInsertTextFieldText(tPtr, buffer, tPtr->cursorPosition);
|
||||
}
|
||||
}
|
||||
if (refresh) {
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
WMPostNotificationName(WMTextDidChangeNotification, tPtr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
pointToCursorPosition(TextField *tPtr, int x)
|
||||
{
|
||||
WMFont *font = tPtr->view->screen->normalFont;
|
||||
int a, b, mid;
|
||||
int tw;
|
||||
|
||||
if (tPtr->flags.bordered)
|
||||
x -= 2;
|
||||
|
||||
a = tPtr->viewPosition;
|
||||
b = tPtr->viewPosition + tPtr->textLen;
|
||||
if (WMWidthOfString(font, &(tPtr->text[tPtr->viewPosition]),
|
||||
tPtr->textLen-tPtr->viewPosition) < x)
|
||||
return tPtr->textLen;
|
||||
|
||||
while (a < b && b-a>1) {
|
||||
mid = (a+b)/2;
|
||||
tw = WMWidthOfString(font, &(tPtr->text[tPtr->viewPosition]),
|
||||
mid - tPtr->viewPosition);
|
||||
if (tw > x)
|
||||
b = mid;
|
||||
else if (tw < x)
|
||||
a = mid;
|
||||
else
|
||||
return mid;
|
||||
}
|
||||
return (a+b)/2;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleTextFieldActionEvents(XEvent *event, void *data)
|
||||
{
|
||||
TextField *tPtr = (TextField*)data;
|
||||
|
||||
CHECK_CLASS(data, WC_TextField);
|
||||
|
||||
switch (event->type) {
|
||||
case KeyPress:
|
||||
if (tPtr->flags.enabled)
|
||||
handleTextFieldKeyPress(tPtr, event);
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
if (tPtr->flags.enabled && (event->xmotion.state & Button1Mask)) {
|
||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
event->xmotion.x);
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
if (tPtr->flags.enabled && !tPtr->flags.focused) {
|
||||
WMSetFocusToWidget(tPtr);
|
||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
event->xbutton.x);
|
||||
paintTextField(tPtr);
|
||||
} else if (tPtr->flags.focused) {
|
||||
tPtr->cursorPosition = pointToCursorPosition(tPtr,
|
||||
event->xbutton.x);
|
||||
paintTextField(tPtr);
|
||||
}
|
||||
if (event->xbutton.button == Button2) {
|
||||
char *text;
|
||||
|
||||
text = W_GetTextSelection(tPtr->view->screen, XA_PRIMARY);
|
||||
if (!text) {
|
||||
text = W_GetTextSelection(tPtr->view->screen, XA_CUT_BUFFER0);
|
||||
}
|
||||
if (text) {
|
||||
WMInsertTextFieldText(tPtr, text, tPtr->cursorPosition);
|
||||
XFree(text);
|
||||
WMPostNotificationName(WMTextDidChangeNotification, tPtr,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
destroyTextField(TextField *tPtr)
|
||||
{
|
||||
#if 0
|
||||
if (tPtr->timerID)
|
||||
WMDeleteTimerHandler(tPtr->timerID);
|
||||
#endif
|
||||
|
||||
if (tPtr->text)
|
||||
free(tPtr->text);
|
||||
|
||||
free(tPtr);
|
||||
}
|
||||
663
WINGs/wview.c
Normal file
663
WINGs/wview.c
Normal file
@@ -0,0 +1,663 @@
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <X11/Xresource.h>
|
||||
|
||||
|
||||
|
||||
/* the notifications about views */
|
||||
|
||||
char *WMViewSizeDidChangeNotification = "WMViewSizeDidChangeNotification";
|
||||
char *WMViewFocusDidChangeNotification = "WMViewFocusDidChangeNotification";
|
||||
char *WMViewRealizedNotification = "WMViewRealizedNotification";
|
||||
|
||||
|
||||
#define EVENT_MASK \
|
||||
KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
|
||||
EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
|
||||
VisibilityChangeMask|FocusChangeMask|PropertyChangeMask|\
|
||||
SubstructureNotifyMask|SubstructureRedirectMask
|
||||
|
||||
|
||||
static XSetWindowAttributes defAtts= {
|
||||
None, /* background_pixmap */
|
||||
0, /* background_pixel */
|
||||
CopyFromParent, /* border_pixmap */
|
||||
0, /* border_pixel */
|
||||
ForgetGravity, /* bit_gravity */
|
||||
ForgetGravity, /* win_gravity */
|
||||
NotUseful, /* backing_store */
|
||||
(unsigned) ~0, /* backing_planes */
|
||||
0, /* backing_pixel */
|
||||
False, /* save_under */
|
||||
EVENT_MASK, /* event_mask */
|
||||
0, /* do_not_propagate_mask */
|
||||
False, /* override_redirect */
|
||||
None, /* colormap */
|
||||
None /* cursor */
|
||||
};
|
||||
|
||||
|
||||
|
||||
static XContext ViewContext=0; /* context for views */
|
||||
|
||||
|
||||
|
||||
|
||||
W_View*
|
||||
W_GetViewForXWindow(Display *display, Window window)
|
||||
{
|
||||
W_View *view;
|
||||
|
||||
if (XFindContext(display, window, ViewContext, (XPointer*)&view)==0) {
|
||||
return view;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
unparentView(W_View *view)
|
||||
{
|
||||
/* remove from parent's children list */
|
||||
if (view->parent!=NULL) {
|
||||
W_View *ptr;
|
||||
|
||||
ptr = view->parent->childrenList;
|
||||
if (ptr == view) {
|
||||
view->parent->childrenList = view->nextSister;
|
||||
} else {
|
||||
while (ptr!=NULL) {
|
||||
if (ptr->nextSister == view) {
|
||||
ptr->nextSister = view->nextSister;
|
||||
break;
|
||||
}
|
||||
ptr = ptr->nextSister;
|
||||
}
|
||||
}
|
||||
}
|
||||
view->parent = NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
adoptChildView(W_View *view, W_View *child)
|
||||
{
|
||||
child->nextSister = NULL;
|
||||
|
||||
/* add to end of children list of parent */
|
||||
if (view->childrenList == NULL) {
|
||||
view->childrenList = child;
|
||||
} else {
|
||||
W_View *ptr;
|
||||
|
||||
ptr = view->childrenList;
|
||||
while (ptr->nextSister!=NULL)
|
||||
ptr = ptr->nextSister;
|
||||
ptr->nextSister = child;
|
||||
}
|
||||
child->parent = view;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *data)
|
||||
{
|
||||
W_View *view = (W_View*)data;
|
||||
|
||||
if (event->type == ConfigureNotify) {
|
||||
|
||||
if (event->xconfigure.width != view->size.width
|
||||
|| event->xconfigure.height != view->size.height) {
|
||||
|
||||
if (view->flags.notifySizeChanged) {
|
||||
view->size.width = event->xconfigure.width;
|
||||
view->size.height = event->xconfigure.height;
|
||||
WMPostNotificationName(WMViewSizeDidChangeNotification,
|
||||
view, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static W_View*
|
||||
createView(W_Screen *screen, W_View *parent)
|
||||
{
|
||||
W_View *view;
|
||||
|
||||
if (ViewContext==0)
|
||||
ViewContext = XUniqueContext();
|
||||
|
||||
view = wmalloc(sizeof(W_View));
|
||||
memset(view, 0, sizeof(W_View));
|
||||
|
||||
view->refCount = 1;
|
||||
|
||||
view->screen = screen;
|
||||
|
||||
if (parent!=NULL) {
|
||||
/* attributes are not valid for root window */
|
||||
view->attribFlags = CWEventMask|CWBitGravity;
|
||||
view->attribs = defAtts;
|
||||
|
||||
view->attribFlags |= CWBackPixel|CWColormap;
|
||||
view->attribs.background_pixel = W_PIXEL(screen->gray);
|
||||
view->attribs.colormap = screen->colormap;
|
||||
|
||||
adoptChildView(parent, view);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
|
||||
W_View*
|
||||
W_CreateView(W_View *parent)
|
||||
{
|
||||
return createView(parent->screen, parent);
|
||||
}
|
||||
|
||||
|
||||
W_View*
|
||||
W_CreateRootView(W_Screen *screen)
|
||||
{
|
||||
W_View *view;
|
||||
|
||||
view = createView(screen, NULL);
|
||||
|
||||
view->window = screen->rootWin;
|
||||
|
||||
view->flags.realized = 1;
|
||||
view->flags.mapped = 1;
|
||||
view->flags.root = 1;
|
||||
|
||||
view->size.width =
|
||||
WidthOfScreen(ScreenOfDisplay(screen->display, screen->screen));
|
||||
view->size.height =
|
||||
HeightOfScreen(ScreenOfDisplay(screen->display, screen->screen));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
W_View*
|
||||
W_CreateTopView(W_Screen *screen)
|
||||
{
|
||||
W_View *view;
|
||||
|
||||
view = createView(screen, screen->rootView);
|
||||
if (!view)
|
||||
return NULL;
|
||||
|
||||
view->flags.topLevel = 1;
|
||||
view->attribs.event_mask |= StructureNotifyMask;
|
||||
|
||||
/* catch changes in the toplevel window (resize from user etc.) */
|
||||
WMCreateEventHandler(view, StructureNotifyMask, handleEvents, view);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
W_RealizeView(W_View *view)
|
||||
{
|
||||
Window parentWID;
|
||||
Display *dpy = view->screen->display;
|
||||
W_View *ptr;
|
||||
|
||||
assert(view->size.width > 0);
|
||||
assert(view->size.height > 0);
|
||||
|
||||
|
||||
if (view->parent && !view->parent->flags.realized) {
|
||||
wwarning("trying to realize widget of unrealized parent");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!view->flags.realized) {
|
||||
parentWID = view->parent->window;
|
||||
view->window = XCreateWindow(dpy, parentWID, view->pos.x, view->pos.y,
|
||||
view->size.width, view->size.height, 0,
|
||||
view->screen->depth, InputOutput,
|
||||
view->screen->visual, view->attribFlags,
|
||||
&view->attribs);
|
||||
|
||||
XSaveContext(dpy, view->window, ViewContext, (XPointer)view);
|
||||
|
||||
view->flags.realized = 1;
|
||||
|
||||
if (view->flags.mapWhenRealized) {
|
||||
W_MapView(view);
|
||||
view->flags.mapWhenRealized = 0;
|
||||
}
|
||||
|
||||
WMPostNotificationName(WMViewRealizedNotification, view, NULL);
|
||||
}
|
||||
|
||||
/* realize children */
|
||||
ptr = view->childrenList;
|
||||
while (ptr!=NULL) {
|
||||
W_RealizeView(ptr);
|
||||
|
||||
ptr = ptr->nextSister;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Bool
|
||||
W_CheckInternalMessage(W_Screen *scr, XClientMessageEvent *cev, int event)
|
||||
{
|
||||
if (cev->message_type == scr->internalMessage
|
||||
&& cev->format == 32 && cev->data.l[1] == event)
|
||||
return True;
|
||||
else
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_ReparentView(W_View *view, W_View *newParent)
|
||||
{
|
||||
int wasMapped;
|
||||
Display *dpy = view->screen->display;
|
||||
|
||||
assert(!view->flags.topLevel);
|
||||
|
||||
wasMapped = view->flags.mapped;
|
||||
if (wasMapped)
|
||||
W_UnmapView(view);
|
||||
|
||||
unparentView(view);
|
||||
adoptChildView(newParent, view);
|
||||
|
||||
if (view->flags.realized) {
|
||||
if (newParent->flags.realized) {
|
||||
XReparentWindow(dpy, view->window, newParent->window, 0, 0);
|
||||
} else {
|
||||
wwarning("trying to reparent realized view to unrealized parent");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
view->pos.x = 0;
|
||||
view->pos.y = 0;
|
||||
|
||||
if (wasMapped)
|
||||
W_MapView(view);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
W_MapView(W_View *view)
|
||||
{
|
||||
if (!view->flags.mapped) {
|
||||
if (view->flags.realized) {
|
||||
XMapRaised(view->screen->display, view->window);
|
||||
XFlush(view->screen->display);
|
||||
view->flags.mapped = 1;
|
||||
} else {
|
||||
view->flags.mapWhenRealized = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* W_MapSubviews-
|
||||
* maps all children of the current view that where already realized.
|
||||
*/
|
||||
void
|
||||
W_MapSubviews(W_View *view)
|
||||
{
|
||||
XMapSubwindows(view->screen->display, view->window);
|
||||
XFlush(view->screen->display);
|
||||
|
||||
view = view->childrenList;
|
||||
while (view) {
|
||||
view->flags.mapped = 1;
|
||||
view->flags.mapWhenRealized = 0;
|
||||
view = view->nextSister;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
W_UnmapSubviews(W_View *view)
|
||||
{
|
||||
XUnmapSubwindows(view->screen->display, view->window);
|
||||
XFlush(view->screen->display);
|
||||
|
||||
view = view->childrenList;
|
||||
while (view) {
|
||||
view->flags.mapped = 0;
|
||||
view->flags.mapWhenRealized = 0;
|
||||
view = view->nextSister;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
W_UnmapView(W_View *view)
|
||||
{
|
||||
view->flags.mapWhenRealized = 0;
|
||||
if (!view->flags.mapped)
|
||||
return;
|
||||
|
||||
XUnmapWindow(view->screen->display, view->window);
|
||||
XFlush(view->screen->display);
|
||||
|
||||
view->flags.mapped = 0;
|
||||
}
|
||||
|
||||
|
||||
W_View*
|
||||
W_TopLevelOfView(W_View *view)
|
||||
{
|
||||
W_View *toplevel;
|
||||
|
||||
for (toplevel=view; !toplevel->flags.topLevel; toplevel=toplevel->parent);
|
||||
|
||||
return toplevel;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
destroyView(W_View *view)
|
||||
{
|
||||
W_View *ptr;
|
||||
|
||||
if (view->flags.alreadyDead)
|
||||
return;
|
||||
view->flags.alreadyDead = 1;
|
||||
|
||||
/* Do not leave focus in a inexisting control */
|
||||
if (W_FocusedViewOfToplevel(W_TopLevelOfView(view))==view)
|
||||
W_SetFocusOfTopLevel(W_TopLevelOfView(view), NULL);
|
||||
|
||||
if (view->flags.topLevel) {
|
||||
W_FocusInfo *info = view->screen->focusInfo;
|
||||
/* remove focus information associated to this toplevel */
|
||||
|
||||
if (info) {
|
||||
if (info->toplevel==view) {
|
||||
view->screen->focusInfo = info->next;
|
||||
free(info);
|
||||
} else {
|
||||
while (info->next) {
|
||||
if (info->next->toplevel == view)
|
||||
break;
|
||||
info = info->next;
|
||||
}
|
||||
if (info->next) {
|
||||
W_FocusInfo *next = info->next->next;
|
||||
free(info->next);
|
||||
info->next = next;
|
||||
}
|
||||
/* else the toplevel did not have any focused subview */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* destroy children recursively */
|
||||
while (view->childrenList!=NULL) {
|
||||
ptr = view->childrenList;
|
||||
ptr->flags.parentDying = 1;
|
||||
|
||||
W_DestroyView(ptr);
|
||||
|
||||
if (ptr == view->childrenList) {
|
||||
view->childrenList = ptr->nextSister;
|
||||
ptr->parent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
W_CallDestroyHandlers(view);
|
||||
|
||||
if (view->flags.realized) {
|
||||
XDeleteContext(view->screen->display, view->window, ViewContext);
|
||||
|
||||
/* if parent is being destroyed, it will die naturaly */
|
||||
if (!view->flags.parentDying || view->flags.topLevel)
|
||||
XDestroyWindow(view->screen->display, view->window);
|
||||
}
|
||||
|
||||
/* remove self from parent's children list */
|
||||
unparentView(view);
|
||||
|
||||
W_CleanUpEvents(view);
|
||||
#if 0
|
||||
if (view->dragSourceProcs)
|
||||
free(view->dragSourceProcs);
|
||||
|
||||
if (view->dragDestinationProcs)
|
||||
free(view->dragDestinationProcs);
|
||||
#endif
|
||||
free(view);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
W_DestroyView(W_View *view)
|
||||
{
|
||||
W_ReleaseView(view);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
W_MoveView(W_View *view, int x, int y)
|
||||
{
|
||||
assert(view->flags.root==0);
|
||||
|
||||
if (view->pos.x == x && view->pos.y == y)
|
||||
return;
|
||||
|
||||
if (view->flags.realized) {
|
||||
XMoveWindow(view->screen->display, view->window, x, y);
|
||||
}
|
||||
view->pos.x = x;
|
||||
view->pos.y = y;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_ResizeView(W_View *view, unsigned int width, unsigned int height)
|
||||
{
|
||||
int shrinked;
|
||||
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
|
||||
if (view->size.width == width && view->size.height == height)
|
||||
return;
|
||||
|
||||
shrinked = width < view->size.width || height < view->size.height;
|
||||
|
||||
if (view->flags.realized) {
|
||||
XResizeWindow(view->screen->display, view->window, width, height);
|
||||
}
|
||||
view->size.width = width;
|
||||
view->size.height = height;
|
||||
|
||||
if (view->flags.notifySizeChanged)
|
||||
WMPostNotificationName(WMViewSizeDidChangeNotification, view, NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_RedisplayView(W_View *view)
|
||||
{
|
||||
XExposeEvent ev;
|
||||
|
||||
if (!view->flags.mapped)
|
||||
return;
|
||||
|
||||
ev.type = Expose;
|
||||
ev.display = view->screen->display;
|
||||
ev.window = view->window;
|
||||
ev.count = 0;
|
||||
|
||||
WMHandleEvent((XEvent*)&ev);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_SetViewBackgroundColor(W_View *view, WMColor *color)
|
||||
{
|
||||
view->attribFlags |= CWBackPixel;
|
||||
view->attribs.background_pixel = color->color.pixel;
|
||||
if (view->flags.realized) {
|
||||
XSetWindowBackground(view->screen->display, view->window,
|
||||
color->color.pixel);
|
||||
XClearWindow(view->screen->display, view->window);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
W_View*
|
||||
W_FocusedViewOfToplevel(W_View *view)
|
||||
{
|
||||
WMScreen *scr = view->screen;
|
||||
W_FocusInfo *info;
|
||||
|
||||
for (info = scr->focusInfo; info!=NULL; info = info->next)
|
||||
if (view == info->toplevel)
|
||||
break;
|
||||
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return info->focused;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_SetFocusOfTopLevel(W_View *toplevel, W_View *view)
|
||||
{
|
||||
WMScreen *scr = toplevel->screen;
|
||||
XEvent event;
|
||||
W_FocusInfo *info;
|
||||
|
||||
for (info = scr->focusInfo; info!=NULL; info = info->next)
|
||||
if (toplevel == info->toplevel)
|
||||
break;
|
||||
|
||||
if (!info) {
|
||||
info = wmalloc(sizeof(W_FocusInfo));
|
||||
info->toplevel = toplevel;
|
||||
info->focused = view;
|
||||
info->next = scr->focusInfo;
|
||||
scr->focusInfo = info;
|
||||
} else {
|
||||
event.xfocus.mode = NotifyNormal;
|
||||
event.xfocus.detail = NotifyDetailNone;
|
||||
if (info->focused) {
|
||||
/* simulate FocusOut event */
|
||||
event.xfocus.type = FocusOut;
|
||||
W_DispatchMessage(info->focused, &event);
|
||||
}
|
||||
info->focused = view;
|
||||
}
|
||||
if (view) {
|
||||
/* simulate FocusIn event */
|
||||
event.xfocus.type = FocusIn;
|
||||
W_DispatchMessage(view, &event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_BroadcastMessage(W_View *targetParent, XEvent *event)
|
||||
{
|
||||
W_View *target;
|
||||
|
||||
target = targetParent->childrenList;
|
||||
while (target!=NULL) {
|
||||
W_DispatchMessage(target, event);
|
||||
|
||||
target = target->nextSister;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
W_DispatchMessage(W_View *target, XEvent *event)
|
||||
{
|
||||
if (target->window==None)
|
||||
return;
|
||||
event->xclient.window = target->window;
|
||||
event->xclient.display = target->screen->display;
|
||||
|
||||
WMHandleEvent(event);
|
||||
/*
|
||||
XSendEvent(target->screen->display, target->window, False,
|
||||
SubstructureNotifyMask, event);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMView*
|
||||
W_RetainView(WMView *view)
|
||||
{
|
||||
view->refCount++;
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
W_ReleaseView(WMView *view)
|
||||
{
|
||||
view->refCount--;
|
||||
if (view->refCount < 1) {
|
||||
destroyView(view);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WMWidget*
|
||||
WMWidgetOfView(WMView *view)
|
||||
{
|
||||
return view->self;
|
||||
}
|
||||
|
||||
|
||||
WMSize
|
||||
WMGetViewSize(WMView *view)
|
||||
{
|
||||
return view->size;
|
||||
}
|
||||
|
||||
WMPoint
|
||||
WMGetViewPosition(WMView *view)
|
||||
{
|
||||
return view->pos;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetViewNotifySizeChanges(WMView *view, Bool flag)
|
||||
{
|
||||
view->flags.notifySizeChanged = flag;
|
||||
}
|
||||
|
||||
Window
|
||||
WMViewXID(WMView *view)
|
||||
{
|
||||
return view->window;
|
||||
}
|
||||
|
||||
646
WINGs/wwindow.c
Normal file
646
WINGs/wwindow.c
Normal file
@@ -0,0 +1,646 @@
|
||||
|
||||
#include <X11/Xmd.h>
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
|
||||
typedef struct W_Window {
|
||||
W_Class widgetClass;
|
||||
W_View *view;
|
||||
|
||||
struct W_Window *nextPtr; /* next in the window list */
|
||||
|
||||
struct W_Window *owner;
|
||||
|
||||
char *title;
|
||||
|
||||
WMPixmap *miniImage; /* miniwindow */
|
||||
char *miniTitle;
|
||||
|
||||
char *wname;
|
||||
|
||||
WMSize resizeIncrement;
|
||||
WMSize baseSize;
|
||||
WMSize minSize;
|
||||
WMSize maxSize;
|
||||
|
||||
WMAction *closeAction;
|
||||
void *closeData;
|
||||
|
||||
int level;
|
||||
|
||||
struct {
|
||||
unsigned style:4;
|
||||
unsigned configured:1;
|
||||
unsigned documentEdited:1;
|
||||
unsigned moved:1;
|
||||
} flags;
|
||||
} _Window;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
CARD32 flags;
|
||||
CARD32 window_style;
|
||||
CARD32 window_level;
|
||||
CARD32 reserved;
|
||||
Pixmap miniaturize_pixmap; /* pixmap for miniaturize button */
|
||||
Pixmap close_pixmap; /* pixmap for close button */
|
||||
Pixmap miniaturize_mask; /* miniaturize pixmap mask */
|
||||
Pixmap close_mask; /* close pixmap mask */
|
||||
CARD32 extra_flags;
|
||||
} GNUstepWMAttributes;
|
||||
|
||||
#define GSWindowStyleAttr (1<<0)
|
||||
#define GSWindowLevelAttr (1<<1)
|
||||
#define GSMiniaturizePixmapAttr (1<<3)
|
||||
#define GSClosePixmapAttr (1<<4)
|
||||
#define GSMiniaturizeMaskAttr (1<<5)
|
||||
#define GSCloseMaskAttr (1<<6)
|
||||
#define GSExtraFlagsAttr (1<<7)
|
||||
|
||||
/* extra flags */
|
||||
#define GSDocumentEditedFlag (1<<0)
|
||||
#define GSNoApplicationIconFlag (1<<5)
|
||||
|
||||
#define WMFHideOtherApplications 10
|
||||
#define WMFHideApplication 12
|
||||
|
||||
|
||||
|
||||
static void resizeWindow(WMWidget *, unsigned, unsigned);
|
||||
static void moveWindow(WMWidget *, int, int);
|
||||
|
||||
struct W_ViewProcedureTable _WindowViewProcedures = {
|
||||
NULL,
|
||||
resizeWindow,
|
||||
moveWindow
|
||||
};
|
||||
|
||||
|
||||
#define DEFAULT_WIDTH 400
|
||||
#define DEFAULT_HEIGHT 180
|
||||
#define DEFAULT_TITLE ""
|
||||
|
||||
|
||||
static void destroyWindow(_Window *win);
|
||||
|
||||
static void handleEvents();
|
||||
|
||||
static void realizeWindow();
|
||||
|
||||
static void
|
||||
realizeObserver(void *self, WMNotification *not)
|
||||
{
|
||||
realizeWindow(self);
|
||||
}
|
||||
|
||||
|
||||
WMWindow*
|
||||
WMCreatePanelWithStyleForWindow(WMWindow *owner, char *name, int style)
|
||||
{
|
||||
WMWindow *win;
|
||||
|
||||
win = WMCreateWindowWithStyle(owner->view->screen, name, style);
|
||||
win->owner = owner;
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMWindow*
|
||||
WMCreatePanelForWindow(WMWindow *owner, char *name)
|
||||
{
|
||||
return WMCreatePanelWithStyleForWindow(owner, name,
|
||||
WMTitledWindowMask
|
||||
|WMClosableWindowMask
|
||||
|WMResizableWindowMask);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMChangePanelOwner(WMWindow *win, WMWindow *newOwner)
|
||||
{
|
||||
win->owner = newOwner;
|
||||
|
||||
if (win->view->flags.realized && newOwner) {
|
||||
XSetTransientForHint(win->view->screen->display, win->view->window,
|
||||
newOwner->view->window);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMWindow*
|
||||
WMCreateWindow(WMScreen *screen, char *name)
|
||||
{
|
||||
return WMCreateWindowWithStyle(screen, name, WMTitledWindowMask
|
||||
|WMClosableWindowMask
|
||||
|WMMiniaturizableWindowMask
|
||||
|WMResizableWindowMask);
|
||||
}
|
||||
|
||||
|
||||
|
||||
WMWindow*
|
||||
WMCreateWindowWithStyle(WMScreen *screen, char *name, int style)
|
||||
{
|
||||
_Window *win;
|
||||
static int initedApp = 0;
|
||||
|
||||
win = wmalloc(sizeof(_Window));
|
||||
memset(win, 0, sizeof(_Window));
|
||||
|
||||
win->widgetClass = WC_Window;
|
||||
|
||||
win->view = W_CreateTopView(screen);
|
||||
if (!win->view) {
|
||||
free(win);
|
||||
return NULL;
|
||||
}
|
||||
win->view->self = win;
|
||||
|
||||
win->wname = wstrdup(name);
|
||||
|
||||
/* add to the window list of the screen (application) */
|
||||
win->nextPtr = screen->windowList;
|
||||
screen->windowList = win;
|
||||
|
||||
WMCreateEventHandler(win->view, ExposureMask|StructureNotifyMask
|
||||
|ClientMessageMask|FocusChangeMask, handleEvents,
|
||||
win);
|
||||
|
||||
W_ResizeView(win->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
||||
|
||||
if (!initedApp) {
|
||||
W_InitApplication(screen);
|
||||
initedApp = 1;
|
||||
}
|
||||
|
||||
WMAddNotificationObserver(realizeObserver, win,
|
||||
WMViewRealizedNotification, win->view);
|
||||
|
||||
win->flags.style = style;
|
||||
|
||||
win->level = WMNormalWindowLevel;
|
||||
|
||||
/* kluge. Find a better solution */
|
||||
W_SetFocusOfTopLevel(win->view, win->view);
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowTitle(WMWindow *win, char *title)
|
||||
{
|
||||
if (win->title!=NULL)
|
||||
free(win->title);
|
||||
if (title!=NULL)
|
||||
win->title = wstrdup(title);
|
||||
else
|
||||
win->title = NULL;
|
||||
|
||||
if (win->view->flags.realized) {
|
||||
XStoreName(win->view->screen->display, win->view->window, title);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowCloseAction(WMWindow *win, WMAction *action, void *clientData)
|
||||
{
|
||||
Atom *atoms = NULL;
|
||||
Atom *newAtoms;
|
||||
int count;
|
||||
WMScreen *scr = win->view->screen;
|
||||
|
||||
if (win->view->flags.realized) {
|
||||
if (action && !win->closeAction) {
|
||||
if (!XGetWMProtocols(scr->display, win->view->window, &atoms,
|
||||
&count)) {
|
||||
count = 0;
|
||||
}
|
||||
newAtoms = wmalloc((count+1)*sizeof(Atom));
|
||||
if (count > 0)
|
||||
memcpy(newAtoms, atoms, count*sizeof(Atom));
|
||||
newAtoms[count++] = scr->deleteWindowAtom;
|
||||
XSetWMProtocols(scr->display, win->view->window, newAtoms, count);
|
||||
if (atoms)
|
||||
XFree(atoms);
|
||||
free(newAtoms);
|
||||
} else if (!action && win->closeAction) {
|
||||
int i, ncount;
|
||||
|
||||
if (XGetWMProtocols(scr->display, win->view->window, &atoms,
|
||||
&count) && count>0) {
|
||||
newAtoms = wmalloc((count-1)*sizeof(Atom));
|
||||
ncount = 0;
|
||||
for (i=0; i < count; i++) {
|
||||
if (atoms[i]!=scr->deleteWindowAtom) {
|
||||
newAtoms[i] = atoms[i];
|
||||
ncount++;
|
||||
}
|
||||
}
|
||||
XSetWMProtocols(scr->display, win->view->window, newAtoms,
|
||||
ncount);
|
||||
if (atoms)
|
||||
XFree(atoms);
|
||||
free(newAtoms);
|
||||
}
|
||||
}
|
||||
}
|
||||
win->closeAction = action;
|
||||
win->closeData = clientData;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
moveWindow(WMWidget *w, int x, int y)
|
||||
{
|
||||
((WMWindow*)w)->flags.moved = 1;
|
||||
|
||||
W_MoveView(W_VIEW(w), x, y);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
resizeWindow(WMWidget *w, unsigned width, unsigned height)
|
||||
{
|
||||
WMWindow *win = (WMWindow*)w;
|
||||
|
||||
if (win->minSize.width > 0 && win->minSize.height > 0) {
|
||||
if (width < win->minSize.width)
|
||||
width = win->minSize.width;
|
||||
if (height < win->minSize.height)
|
||||
height = win->minSize.height;
|
||||
}
|
||||
|
||||
if (win->maxSize.width > 0 && win->maxSize.height > 0) {
|
||||
if (width > win->maxSize.width)
|
||||
width = win->maxSize.width;
|
||||
if (height > win->maxSize.height)
|
||||
height = win->maxSize.height;
|
||||
}
|
||||
|
||||
W_ResizeView(win->view, width, height);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
setSizeHints(WMWindow *win)
|
||||
{
|
||||
XSizeHints *hints;
|
||||
|
||||
hints = XAllocSizeHints();
|
||||
if (!hints) {
|
||||
wwarning("could not allocate memory for window size hints");
|
||||
return;
|
||||
}
|
||||
|
||||
hints->flags = 0;
|
||||
if (win->minSize.width>0 && win->minSize.height>0) {
|
||||
hints->flags |= PMinSize;
|
||||
hints->min_width = win->minSize.width;
|
||||
hints->min_height = win->minSize.height;
|
||||
}
|
||||
if (win->maxSize.width>0 && win->maxSize.height>0) {
|
||||
hints->flags |= PMaxSize;
|
||||
hints->max_width = win->maxSize.width;
|
||||
hints->max_height = win->maxSize.height;
|
||||
}
|
||||
if (win->baseSize.width>0 && win->baseSize.height>0) {
|
||||
hints->flags |= PBaseSize;
|
||||
hints->base_width = win->baseSize.width;
|
||||
hints->base_height = win->baseSize.height;
|
||||
}
|
||||
if (win->resizeIncrement.width>0 && win->resizeIncrement.height>0) {
|
||||
hints->flags |= PResizeInc;
|
||||
hints->width_inc = win->resizeIncrement.width;
|
||||
hints->height_inc = win->resizeIncrement.height;
|
||||
}
|
||||
|
||||
if (hints->flags) {
|
||||
XSetWMNormalHints(win->view->screen->display, win->view->window, hints);
|
||||
}
|
||||
XFree(hints);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
writeGNUstepWMAttr(WMScreen *scr, Window window, GNUstepWMAttributes *attr)
|
||||
{
|
||||
CARD32 data[9];
|
||||
|
||||
/* handle idiot compilers where array of CARD32 != struct of CARD32 */
|
||||
data[0] = attr->flags;
|
||||
data[1] = attr->window_style;
|
||||
data[2] = attr->window_level;
|
||||
data[3] = 0; /* reserved */
|
||||
/* The X protocol says XIDs are 32bit */
|
||||
data[4] = attr->miniaturize_pixmap;
|
||||
data[5] = attr->close_pixmap;
|
||||
data[6] = attr->miniaturize_mask;
|
||||
data[7] = attr->close_mask;
|
||||
data[8] = attr->extra_flags;
|
||||
XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
|
||||
32, PropModeReplace, (unsigned char *)data, 9);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
setWindowMakerHints(WMWindow *win)
|
||||
{
|
||||
GNUstepWMAttributes attribs;
|
||||
WMScreen *scr = WMWidgetScreen(win);
|
||||
|
||||
memset(&attribs, 0, sizeof(GNUstepWMAttributes));
|
||||
attribs.flags = GSWindowStyleAttr|GSWindowLevelAttr|GSExtraFlagsAttr;
|
||||
attribs.window_style = win->flags.style;
|
||||
attribs.window_level = win->level;
|
||||
if (win->flags.documentEdited)
|
||||
attribs.extra_flags = GSDocumentEditedFlag;
|
||||
else
|
||||
attribs.extra_flags = 0;
|
||||
|
||||
writeGNUstepWMAttr(scr, win->view->window, &attribs);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
realizeWindow(WMWindow *win)
|
||||
{
|
||||
XWMHints *hints;
|
||||
XClassHint *classHint;
|
||||
WMScreen *scr = win->view->screen;
|
||||
Atom atoms[4];
|
||||
int count;
|
||||
|
||||
if (!win->flags.moved && win->owner!=NULL) {
|
||||
W_MoveView(win->view,
|
||||
(scr->rootView->size.width-win->view->size.width)/2,
|
||||
(scr->rootView->size.height-win->view->size.height)/2);
|
||||
}
|
||||
|
||||
classHint = XAllocClassHint();
|
||||
classHint->res_name = win->wname;
|
||||
classHint->res_class = WMGetApplicationName();
|
||||
XSetClassHint(scr->display, win->view->window, classHint);
|
||||
XFree(classHint);
|
||||
|
||||
hints = XAllocWMHints();
|
||||
hints->flags = 0;
|
||||
if (!scr->aflags.simpleApplication) {
|
||||
hints->flags |= WindowGroupHint;
|
||||
hints->window_group = scr->groupLeader;
|
||||
}
|
||||
if (win->miniImage) {
|
||||
hints->flags |= IconPixmapHint;
|
||||
hints->icon_pixmap = WMGetPixmapXID(win->miniImage);
|
||||
hints->icon_mask = WMGetPixmapMaskXID(win->miniImage);
|
||||
if (hints->icon_mask != None) {
|
||||
hints->flags |= IconMaskHint;
|
||||
}
|
||||
}
|
||||
if (hints->flags != 0)
|
||||
XSetWMHints(scr->display, win->view->window, hints);
|
||||
XFree(hints);
|
||||
|
||||
count = 0;
|
||||
if (win->closeAction) {
|
||||
atoms[count++] = scr->deleteWindowAtom;
|
||||
}
|
||||
|
||||
if (count>0)
|
||||
XSetWMProtocols(scr->display, win->view->window, atoms, count);
|
||||
|
||||
if (win->title)
|
||||
XStoreName(scr->display, win->view->window, win->title);
|
||||
|
||||
if (win->miniTitle)
|
||||
XSetIconName(scr->display, win->view->window, win->miniTitle);
|
||||
|
||||
setWindowMakerHints(win);
|
||||
|
||||
setSizeHints(win);
|
||||
|
||||
if (win->owner) {
|
||||
XSetTransientForHint(scr->display, win->view->window,
|
||||
win->owner->view->window);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMHideWindow(WMWindow *win)
|
||||
{
|
||||
WMUnmapWidget(win);
|
||||
XWithdrawWindow(win->view->screen->display, win->view->window,
|
||||
win->view->screen->screen);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowMinSize(WMWindow *win, unsigned width, unsigned height)
|
||||
{
|
||||
win->minSize.width = width;
|
||||
win->minSize.height = height;
|
||||
if (win->view->flags.realized)
|
||||
setSizeHints(win);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowMaxSize(WMWindow *win, unsigned width, unsigned height)
|
||||
{
|
||||
win->maxSize.width = width;
|
||||
win->maxSize.height = height;
|
||||
if (win->view->flags.realized)
|
||||
setSizeHints(win);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowBaseSize(WMWindow *win, unsigned width, unsigned height)
|
||||
{
|
||||
/* TODO: validate sizes */
|
||||
win->baseSize.width = width;
|
||||
win->baseSize.height = height;
|
||||
if (win->view->flags.realized)
|
||||
setSizeHints(win);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowResizeIncrements(WMWindow *win, unsigned wIncr, unsigned hIncr)
|
||||
{
|
||||
win->resizeIncrement.width = wIncr;
|
||||
win->resizeIncrement.height = hIncr;
|
||||
if (win->view->flags.realized)
|
||||
setSizeHints(win);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowLevel(WMWindow *win, int level)
|
||||
{
|
||||
win->level = level;
|
||||
if (win->view->flags.realized)
|
||||
setWindowMakerHints(win);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowDocumentEdited(WMWindow *win, Bool flag)
|
||||
{
|
||||
if (win->flags.documentEdited != flag) {
|
||||
win->flags.documentEdited = flag;
|
||||
if (win->view->flags.realized)
|
||||
setWindowMakerHints(win);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowMiniwindowImage(WMWindow *win, WMPixmap *pixmap)
|
||||
{
|
||||
if ((win->miniImage && !pixmap) || (!win->miniImage && pixmap)) {
|
||||
if (win->miniImage)
|
||||
WMReleasePixmap(win->miniImage);
|
||||
|
||||
if (pixmap)
|
||||
win->miniImage = WMRetainPixmap(pixmap);
|
||||
else
|
||||
win->miniImage = NULL;
|
||||
|
||||
if (win->view->flags.realized) {
|
||||
XWMHints *hints;
|
||||
|
||||
hints = XGetWMHints(win->view->screen->display, win->view->window);
|
||||
if (!hints) {
|
||||
hints = XAllocWMHints();
|
||||
if (!hints) {
|
||||
wwarning("could not allocate memory for WM hints");
|
||||
return;
|
||||
}
|
||||
hints->flags = 0;
|
||||
}
|
||||
if (pixmap) {
|
||||
hints->flags |= IconPixmapHint;
|
||||
hints->icon_pixmap = WMGetPixmapXID(pixmap);
|
||||
hints->icon_mask = WMGetPixmapMaskXID(pixmap);
|
||||
if (hints->icon_mask != None) {
|
||||
hints->flags |= IconMaskHint;
|
||||
}
|
||||
}
|
||||
XSetWMHints(win->view->screen->display, win->view->window, hints);
|
||||
XFree(hints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetWindowMiniwindowTitle(WMWindow *win, char *title)
|
||||
{
|
||||
if ((win->miniTitle && !title) || (!win->miniTitle && title)
|
||||
|| (title && win->miniTitle && strcoll(title, win->miniTitle)!=0)) {
|
||||
if (win->miniTitle)
|
||||
free(win->miniTitle);
|
||||
|
||||
if (title)
|
||||
win->miniTitle = wstrdup(title);
|
||||
else
|
||||
win->miniTitle = NULL;
|
||||
|
||||
if (win->view->flags.realized) {
|
||||
XSetIconName(win->view->screen->display, win->view->window, title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMCloseWindow(WMWindow *win)
|
||||
{
|
||||
/* withdraw the window */
|
||||
if (win->view->flags.realized)
|
||||
XWithdrawWindow(win->view->screen->display, win->view->window,
|
||||
win->view->screen->screen);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handleEvents(XEvent *event, void *clientData)
|
||||
{
|
||||
_Window *win = (_Window*)clientData;
|
||||
|
||||
|
||||
switch (event->type) {
|
||||
case ClientMessage:
|
||||
if (event->xclient.message_type == win->view->screen->protocolsAtom
|
||||
&& event->xclient.format == 32
|
||||
&& event->xclient.data.l[0]==win->view->screen->deleteWindowAtom) {
|
||||
|
||||
if (win->closeAction) {
|
||||
(*win->closeAction)(win, win->closeData);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DestroyNotify:
|
||||
destroyWindow(win);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
destroyWindow(_Window *win)
|
||||
{
|
||||
WMScreen *scr = win->view->screen;
|
||||
|
||||
WMRemoveNotificationObserver(win);
|
||||
|
||||
if (scr->windowList == win) {
|
||||
scr->windowList = scr->windowList->nextPtr;
|
||||
} else {
|
||||
WMWindow *ptr;
|
||||
ptr = scr->windowList;
|
||||
|
||||
while (ptr->nextPtr) {
|
||||
if (ptr->nextPtr==win) {
|
||||
ptr->nextPtr = ptr->nextPtr->nextPtr;
|
||||
break;
|
||||
}
|
||||
ptr = ptr->nextPtr;
|
||||
}
|
||||
}
|
||||
|
||||
if (win->title) {
|
||||
free(win->title);
|
||||
}
|
||||
|
||||
if (win->miniTitle) {
|
||||
free(win->miniTitle);
|
||||
}
|
||||
|
||||
if (win->miniImage) {
|
||||
WMReleasePixmap(win->miniImage);
|
||||
}
|
||||
|
||||
if (win->wname)
|
||||
free(win->wname);
|
||||
|
||||
free(win);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user