1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-02-08 01:15:56 +01:00

Initial revision

This commit is contained in:
scottc
1998-09-29 22:36:29 +00:00
commit 9d2e6ef9f1
527 changed files with 138651 additions and 0 deletions

96
WINGs/ChangeLog Normal file
View 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
View 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
View 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
View 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

Binary file not shown.

BIN
WINGs/Resources/Images.xcf Normal file

Binary file not shown.

236
WINGs/Resources/Images.xpm Normal file
View 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 . ",
" . . . . . . . . . . . . . . . . . ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};

View 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
View 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:

Binary file not shown.

View 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
View 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

File diff suppressed because it is too large Load Diff

394
WINGs/WINGsP.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@@ -0,0 +1,12 @@
#include <X11/Xlib.h>
#include "WINGsP.h"
void
InitI18n(Display *dpy)
{
}

56
WINGs/logo.xpm Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}