Added lbreakout2 from original source

This commit is contained in:
Jerome Marty
2010-12-20 16:03:09 +01:00
committed by pelya
parent 661fdabbfc
commit 18a15db3d4
587 changed files with 191221 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
DEFS = @DEFS@ @inst_flag@ @audio_flag@
noinst_LIBRARIES = libGui.a
libGui_a_SOURCES = list.c stk.c \
gui.c gui_widget.c gui_theme.c \
gui_box.c gui_button.c gui_label.c gui_icon.c \
gui_radiogroup.c gui_scrollbar.c gui_progressbar.c \
gui_list.c gui_edit.c gui_spinbutton.c
EXTRA_DIST = list.h stk.h \
gui.h gui_widget.h gui_theme.h \
gui_box.h gui_button.h gui_label.h gui_icon.h \
gui_radiogroup.h gui_scrollbar.h gui_progressbar.h \
gui_list.h gui_edit.h gui_spinbutton.h

View File

@@ -0,0 +1,482 @@
# Makefile.in generated by automake 1.9.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 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.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = gui
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \
$(top_srcdir)/m4/intmax.m4 $(top_srcdir)/m4/inttypes-pri.m4 \
$(top_srcdir)/m4/inttypes.m4 $(top_srcdir)/m4/inttypes_h.m4 \
$(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lcmessage.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/longdouble.m4 \
$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/nls.m4 \
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/signed.m4 \
$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/ulonglong.m4 \
$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
AR = ar
ARFLAGS = cru
libGui_a_AR = $(AR) $(ARFLAGS)
libGui_a_LIBADD =
am_libGui_a_OBJECTS = list.$(OBJEXT) stk.$(OBJEXT) gui.$(OBJEXT) \
gui_widget.$(OBJEXT) gui_theme.$(OBJEXT) gui_box.$(OBJEXT) \
gui_button.$(OBJEXT) gui_label.$(OBJEXT) gui_icon.$(OBJEXT) \
gui_radiogroup.$(OBJEXT) gui_scrollbar.$(OBJEXT) \
gui_progressbar.$(OBJEXT) gui_list.$(OBJEXT) \
gui_edit.$(OBJEXT) gui_spinbutton.$(OBJEXT)
libGui_a_OBJECTS = $(am_libGui_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libGui_a_SOURCES)
DIST_SOURCES = $(libGui_a_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DATADIRNAME = @DATADIRNAME@
DEFS = @DEFS@ @inst_flag@ @audio_flag@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GENCAT = @GENCAT@
GLIBC21 = @GLIBC21@
GMSGFMT = @GMSGFMT@
GREP = @GREP@
HAVE_ASPRINTF = @HAVE_ASPRINTF@
HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@
HAVE_SNPRINTF = @HAVE_SNPRINTF@
HAVE_WPRINTF = @HAVE_WPRINTF@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INSTOBJEXT = @INSTOBJEXT@
INTLBISON = @INTLBISON@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
LDFLAGS = @LDFLAGS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKINSTALLDIRS = @MKINSTALLDIRS@
MSGFMT = @MSGFMT@
MSGMERGE = @MSGMERGE@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
POSUB = @POSUB@
RANLIB = @RANLIB@
SDL_CFLAGS = @SDL_CFLAGS@
SDL_CONFIG = @SDL_CONFIG@
SDL_LIBS = @SDL_LIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
ac_ct_CC = @ac_ct_CC@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
appname = @appname@
arch_flag = @arch_flag@
audio_flag = @audio_flag@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
datarootdir = @datarootdir@
doc_dir = @doc_dir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
hi_dir = @hi_dir@
hi_inst_flag = @hi_inst_flag@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
inst_dir = @inst_dir@
inst_flag = @inst_flag@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
locdir_flag = @locdir_flag@
mandir = @mandir@
mixer_flag = @mixer_flag@
mkdir_p = @mkdir_p@
netdebug_flag = @netdebug_flag@
network_flag = @network_flag@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sdlnet_flag = @sdlnet_flag@
sdlnet_lib_flag = @sdlnet_lib_flag@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
warp_flag = @warp_flag@
win32_deps = @win32_deps@
win32_inst_script = @win32_inst_script@
noinst_LIBRARIES = libGui.a
libGui_a_SOURCES = list.c stk.c \
gui.c gui_widget.c gui_theme.c \
gui_box.c gui_button.c gui_label.c gui_icon.c \
gui_radiogroup.c gui_scrollbar.c gui_progressbar.c \
gui_list.c gui_edit.c gui_spinbutton.c
EXTRA_DIST = list.h stk.h \
gui.h gui_widget.h gui_theme.h \
gui_box.h gui_button.h gui_label.h gui_icon.h \
gui_radiogroup.h gui_scrollbar.h gui_progressbar.h \
gui_list.h gui_edit.h gui_spinbutton.h
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign gui/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --foreign gui/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libGui.a: $(libGui_a_OBJECTS) $(libGui_a_DEPENDENCIES)
-rm -f libGui.a
$(libGui_a_AR) libGui.a $(libGui_a_OBJECTS) $(libGui_a_LIBADD)
$(RANLIB) libGui.a
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_box.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_button.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_edit.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_icon.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_label.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_progressbar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_radiogroup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_scrollbar.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_spinbutton.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_theme.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gui_widget.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stk.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
uninstall-info-am:
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-noinstLIBRARIES ctags distclean distclean-compile \
distclean-generic distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-info-am
# 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:

View File

@@ -0,0 +1,440 @@
/***************************************************************************
gui.c - description
-------------------
begin : Fri Oct 11 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "gui.h"
extern int stk_quit_request;
extern GuiTheme *gui_theme;
extern GuiWidget *gui_clicked_widget;
extern GuiWidget *gui_focused_widget;
extern GuiWidget *gui_key_widget;
/*
====================================================================
This is a list of all root widgets (no parent) created. It is used
to delete all widgets in gui_finalize().
====================================================================
*/
List *gui_root_stack = 0;
/*
====================================================================
This is a list of all visible root widgets updated by
gui_widget_show(). The upper most root widget will handle
events first.
====================================================================
*/
List *gui_visible_stack = 0;
/*
====================================================================
This is a list of all widgets that enabled the GUI_TIME_PASSED
event on creation.
====================================================================
*/
List *gui_timed_stack = 0;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Event filter for mouse motion. Update 'gui_motion_event' with
the latest motion and pass just the very first motion event to
the queue (so we know that it occured)
====================================================================
*/
SDL_EventFilter gui_old_event_filter = 0;
int gui_uses_event_filter = 0;
SDL_Event gui_sdl_motion_event;
int gui_event_filter( const SDL_Event *event )
{
int xrel, yrel;
if ( event->type == SDL_MOUSEMOTION ) {
if ( gui_sdl_motion_event.type == SDL_NOEVENT ) {
/* first occurence */
gui_sdl_motion_event = *event;
}
else {
/* already queued */
xrel = gui_sdl_motion_event.motion.xrel;
yrel = gui_sdl_motion_event.motion.yrel;
gui_sdl_motion_event = *event;
gui_sdl_motion_event.motion.xrel += xrel;
gui_sdl_motion_event.motion.yrel += yrel;
return 0;
}
}
return 1;
}
/*
====================================================================
Check all visible root widgets and update the focus by
assuming the mouse pointer at the position of the passed
GUI_MOTION event which was not necessarily initiated from
an SDL event thus gui_update_focus() can be used to
update the focus if a widget grabbed focus on button pressed.
====================================================================
*/
void gui_update_focus( GuiEvent *gui_event )
{
ListEntry *entry;
GuiWidget *widget = 0;
GuiWidget *next, *new_focus = 0;
/* check all root widgets for new focus */
new_focus = 0;
entry = gui_visible_stack->tail->prev;
while ( entry != gui_visible_stack->head ) {
widget = (GuiWidget*)entry->item;
/* clear widget->focused_widget */
if ( ( next = widget->focused_widget ) ) {
while ( next ) {
next->focused = 0;
next = next->parent;
}
widget->focused_widget = 0;
}
/* get new focused_widget */
gui_widget_update_focus( widget,
gui_event->motion.x, gui_event->motion.y,
&widget->focused_widget );
/* if we have a focused widget this is either
our current or a new focus */
if ( widget->focused_widget ) {
new_focus = widget->focused_widget;
break;
}
/* if 'grab_input' is set we don't check
lower root widgets */
if ( widget->grab_input )
break;
/* next root widget */
entry = entry->prev;
}
/* check relation new_focus/gui_focused_widget */
if ( new_focus == gui_focused_widget ) {
if ( !new_focus ) /* no focus at all */
return;
/* unchanged focus thus motion event */
gui_widget_handle_event(
gui_focused_widget, gui_event );
}
else {
if ( gui_focused_widget ) {
/* focus out event */
gui_event->type = GUI_FOCUS_OUT;
next = gui_focused_widget;
while ( next ) {
next->focused = 0;
next = next->parent;
}
gui_widget_handle_event(
gui_focused_widget, gui_event );
gui_focused_widget = 0;
}
if ( new_focus ) {
/* focus in event */
gui_focused_widget = new_focus;
gui_event->type = GUI_FOCUS_IN;
gui_widget_handle_event(
gui_focused_widget, gui_event );
}
}
}
/*
====================================================================
Handle an SDL event for the visible root widgets and store all
nescessary update rects. If the event was handled by a widget
the user_event_handler is called if one has been installed.
Returns True if the event was handled by the GUI.
====================================================================
*/
static int gui_handle_event( SDL_Event *sdl_event )
{
GuiWidget *widget = 0;
GuiEvent gui_event;
switch ( sdl_event->type ) {
case SDL_QUIT:
stk_quit_request = 1;
return 1;
case SDL_KEYUP:
case SDL_KEYDOWN:
/* a key event is either processed by the
gui_key_widget or gui_focused_widget */
if ( gui_key_widget )
widget = gui_key_widget;
else
widget = gui_focused_widget;
if ( widget ) {
gui_event_init( &gui_event, sdl_event );
gui_widget_handle_event( widget, &gui_event );
return 1;
}
break;
case SDL_MOUSEBUTTONDOWN:
/* if our widget is focused update gui_key_widget */
if ( !gui_focused_widget ) break;
gui_clicked_widget = gui_focused_widget;
widget = gui_focused_widget;
widget->pressed = 1;
if ( widget->grab_keys ) {
if ( gui_key_widget )
gui_key_widget->default_event_handler(
gui_key_widget,
gui_event_get_simple( GUI_FOCUS_OUT ) );
gui_key_widget = widget;
}
gui_event_init( &gui_event, sdl_event );
gui_widget_handle_event( widget, &gui_event );
return 1;
case SDL_MOUSEBUTTONUP:
/* if clicked_widget grabbed focus we need to
update the focus by a fake motion event. */
if ( gui_clicked_widget )
if ( gui_clicked_widget->pressed )
if ( gui_clicked_widget->grab_focus ) {
memset( &gui_event, 0, sizeof( gui_event ) );
gui_event.type = GUI_MOTION;
gui_event.motion.x = sdl_event->button.x;
gui_event.motion.y = sdl_event->button.y;
/* we don't set buttons and relative position
in this fake event so this might cause errors
if the 'focus grabbing' widget requires
these values. however at this point the
only case we need 'grab_focus' is for
scrollbar track buttons. so if this ever
changes don't forget to drop by. ;-) */
gui_update_focus( &gui_event );
}
/* if our focused widget has 'pressed' True
this becomes a CLICKED event. clear 'pressed'
flag in any case*/
if ( !gui_focused_widget ) {
if ( gui_clicked_widget )
gui_clicked_widget->pressed = 0;
break;
}
gui_event_init( &gui_event, sdl_event );
widget = gui_focused_widget;
if ( widget->pressed )
gui_event.type = GUI_CLICKED;
else
gui_event.type = GUI_BUTTON_RELEASED;
if ( gui_clicked_widget )
gui_clicked_widget->pressed = 0;
gui_widget_handle_event( widget, &gui_event );
return 1;
case SDL_MOUSEMOTION:
/* if we use the improved event filter check for
the latest motion event in gui_motion_event */
if ( gui_uses_event_filter ) {
gui_event_init( &gui_event, &gui_sdl_motion_event );
gui_sdl_motion_event.type = SDL_NOEVENT;
}
else
gui_event_init( &gui_event, sdl_event );
/* if clicked widget grabs input do not update the
focus but pass the event directly to clicked_widget */
if ( gui_clicked_widget )
if ( gui_clicked_widget->pressed )
if ( gui_clicked_widget->grab_focus ) {
gui_widget_handle_event( gui_clicked_widget, &gui_event );
break;
}
/* update the focus and sent FOCUS_IN, FOCUS_OUT,
MOTION events */
gui_update_focus( &gui_event );
break;
}
return 0; /* grab input later */
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Initiate the GUI and load the theme either from stk's surface
path or an absolute position. This must be done before any widget
is created. gui_init() installs gui_finalize() as exit function.
====================================================================
*/
void gui_init( char *theme_path )
{
/* load theme */
gui_theme = gui_theme_load( theme_path );
/* all root widgets created. the list is not AUTO_DELETE
to allow direct usage of gui_widget_delete() as well. */
gui_root_stack = list_create(
LIST_NO_AUTO_DELETE, LIST_NO_CALLBACK );
/* visible stack stores pointers to existing root widgets */
gui_visible_stack = list_create(
LIST_NO_AUTO_DELETE, LIST_NO_CALLBACK );
/* timed stack stores pointers to existing widgets */
gui_timed_stack = list_create(
LIST_NO_AUTO_DELETE, LIST_NO_CALLBACK );
/* install gui_finalize() */
atexit( gui_finalize );
}
/*
====================================================================
Finalize GUI and free any memory allocated by gui_init(). Also
delete all widgets that were not destroyed at this point.
====================================================================
*/
void gui_finalize( void )
{
GuiWidget *widget;
if ( gui_root_stack ) {
list_reset( gui_root_stack );
while ( ( widget = list_next( gui_root_stack ) ) )
gui_widget_delete( &widget );
list_delete( gui_root_stack );
gui_root_stack = 0;
}
if ( gui_visible_stack ) {
list_delete( gui_visible_stack );
gui_visible_stack = 0;
}
if ( gui_timed_stack ) {
list_delete( gui_timed_stack );
gui_timed_stack = 0;
}
gui_theme_delete( &gui_theme );
printf( "GUI finalized\n" );
}
/*
====================================================================
Handle SDL and time event for visible root widgets.
If 'event' is not NULL and it is handled by one of the root widgets
True is returned or False otherwise. If a widget within this queue
has 'grab_input' set True 'event' is not handled by lower level
widgets and True is returned.
'ms' is the amount of milliseconds passed since the last call from
gui_dispatch_event(). If 'ms' > 0 a GUI_TIME_PASSED event is sent
to all widgets that enabled the GUI_TIME_PASSED event.
The GUI_TIME_PASSED event is send regardless of 'grab_input'.
WARNING: If a root widget closes itself it's okay but if the
previous widget in visible_stack is closed the entry pointer
becomes invalid when handling the SDL event. FIXME
====================================================================
*/
int gui_dispatch_event( SDL_Event *sdl_event, int ms )
{
ListEntry *entry;
GuiEvent gui_event;
GuiWidget *widget;
int ret = 0;
/* timer event */
if ( ms > 0 ) {
/* of all edits only one needs to blink it's
cursor and handle a pressed key so we by-pass
the clean way of raising a GUI_TIME_PASSED
event and update this edit directly. yes, this
is a hack but it speeds up dispatching and is
within the GUI. no one is hurt. */
widget = gui_key_widget;
if ( !widget ) widget = gui_focused_widget;
if ( widget && widget->type == GUI_EDIT )
gui_edit_update( widget, ms );
/* GUI_TIME_PASSED event */
gui_event.type = GUI_TIME_PASSED;
gui_event.time.ms = ms;
entry = gui_timed_stack->head->next;
while ( entry != gui_timed_stack->tail ) {
widget = (GuiWidget*)entry->item;
if ( !widget->visible ) continue;
gui_widget_call_user_event_handler(
widget, &gui_event );
entry = entry->next;
}
}
/* sdl event */
if ( sdl_event )
ret = gui_handle_event( sdl_event );
return ret;
}
/*
====================================================================
Run all visible root widgets until the 'master' widget is closed.
If there is no root widget open gui_run() will immediately exit.
If 'master' is 0 the gui is run until all root widgets are closed.
====================================================================
*/
void gui_run( GuiWidget *master )
{
SDL_Event event;
int ms;
stk_timer_reset();
while ( 1 ) {
/* break conditions */
if ( stk_quit_request ) break;
if ( master ) {
if ( !master->visible ) break; }
else
if ( gui_visible_stack->count == 0 ) break;
/* get time */
ms = stk_timer_get_time();
/* handle event */
if ( SDL_PollEvent( &event ) )
gui_dispatch_event( &event, ms );
else
gui_dispatch_event( 0, ms );
/* update display */
stk_display_update( STK_UPDATE_RECTS );
/* wait some time */
SDL_Delay( 5 );
}
}
/*
====================================================================
Install a special event filter to improve usage of scrollbars.
gui_disable_event_filter() restores the previous filter.
====================================================================
*/
void gui_enable_event_filter()
{
/* already in use? */
if ( SDL_GetEventFilter() == gui_event_filter )
return;
/* install */
gui_old_event_filter = SDL_GetEventFilter();
SDL_SetEventFilter( gui_event_filter );
gui_sdl_motion_event.type = SDL_NOEVENT;
gui_uses_event_filter = 1;
}
void gui_disable_event_filter()
{
SDL_SetEventFilter( gui_old_event_filter );
gui_uses_event_filter = 0;
}

View File

@@ -0,0 +1,89 @@
/***************************************************************************
gui.h - description
-------------------
begin : Fri Oct 11 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_H
#define __GUI_H
#include "gui_widget.h"
#include "gui_box.h"
#include "gui_label.h"
#include "gui_icon.h"
#include "gui_button.h"
#include "gui_radiogroup.h"
#include "gui_progressbar.h"
#include "gui_scrollbar.h"
#include "gui_edit.h"
#include "gui_list.h"
#include "gui_spinbutton.h"
/*
====================================================================
GUI
====================================================================
*/
/*
====================================================================
Initiate the GUI and load the theme either from stk's surface
path or an absolute position. This must be done before any widget
is created. gui_init() installs gui_finalize() as exit function.
====================================================================
*/
void gui_init( char *theme_path );
/*
====================================================================
Finalize GUI and free any memory allocated by gui_init(). Also
delete all widgets that were not destroyed at this point.
====================================================================
*/
void gui_finalize( void );
/*
====================================================================
Handle SDL and time event for visible root widgets.
If 'event' is not NULL and it is handled by one of the root widgets
True is returned or False otherwise. If a widget within this queue
has 'grab_input' set True 'event' is not handled by lower level
widgets and True is returned.
'ms' is the amount of milliseconds passed since the last call from
gui_dispatch_event(). If 'ms' > 0 a GUI_TIME_PASSED event is sent
to all widgets that enabled the GUI_TIME_PASSED event.
The GUI_TIME_PASSED event is send regardless of 'grab_input'.
====================================================================
*/
int gui_dispatch_event( SDL_Event *event, int ms );
/*
====================================================================
Run all visible root widgets until the 'master' widget is closed.
If there is no root widget open gui_run() will immediately exit.
If 'master' is 0 the gui is run until all root widgets are closed.
====================================================================
*/
void gui_run( GuiWidget *master );
/*
====================================================================
Install a special event filter to improve usage of scrollbars.
gui_disable_event_filter() restores the previous filter.
====================================================================
*/
void gui_enable_event_filter();
void gui_disable_event_filter();
#endif

View File

@@ -0,0 +1,90 @@
/***************************************************************************
gui_box.c - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include "gui_widget.h"
#include "gui_box.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Default event handler
====================================================================
*/
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
switch ( event->type ) {
case GUI_DESTROY:
break;
case GUI_DRAW:
/* display surface */
stk_surface_blit(
widget->surface, 0, 0, -1, -1,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
break;
}
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create a box widget that can be used to contain various other
widgets of any kind. If 'grab_input' is True and this widget is
opened as a root widget it will not pass unhandled events to the
lower-level root widgets thus it blocks events.
====================================================================
*/
GuiWidget* gui_box_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int grab_input )
{
GuiWidget *widget = gui_widget_create(
parent, GUI_BOX, x, y, width, height,
default_event_handler, user_event_handler );
/* create surface, wallpaper and frame it */
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height );
SDL_SetColorKey( widget->surface, 0,0 );
stk_surface_apply_wallpaper( widget->surface, 0,0,-1,-1,
gui_theme->box_wallpaper, -1 );
widget->border = stk_surface_apply_frame(
widget->surface, 0, 0, -1, -1,
(parent==0)?gui_theme->box_frame:gui_theme->widget_frame );
/* various */
widget->width -= 2 * widget->border;
widget->height -= 2 * widget->border;
widget->grab_input = grab_input;
/* done */
return widget;
}

View File

@@ -0,0 +1,35 @@
/***************************************************************************
gui_box.h - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_BOX_H
#define __GUI_BOX_H
/*
====================================================================
Create a box widget that can be used to contain various other
widgets of any kind. If 'grab_input' is True and this widget is
opened as a root widget it will not pass unhandled events to the
lower-level root widgets thus it blocks events.
====================================================================
*/
GuiWidget* gui_box_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int grab_input );
#endif

View File

@@ -0,0 +1,193 @@
/***************************************************************************
gui_button.c - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "gui_widget.h"
#include "gui_button.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Default event handler
====================================================================
*/
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
switch ( event->type ) {
case GUI_DESTROY:
break;
case GUI_DRAW:
/* the button surface provides for states in a
vertical order: normal, focused, clicked,
inactive */
if ( !widget->active ) {
stk_surface_blit( widget->surface,
0, (widget->screen_region.h<<1) +
widget->screen_region.h,
-1, widget->screen_region.h,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
break;
}
if ( widget->focused ) {
if ( widget->pressed )
stk_surface_blit( widget->surface,
0, widget->screen_region.h<<1,
-1, widget->screen_region.h,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
else
stk_surface_blit( widget->surface,
0, widget->screen_region.h,
-1, widget->screen_region.h,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
}
else
stk_surface_blit( widget->surface, 0, 0,
-1, widget->screen_region.h,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
break;
case GUI_BUTTON_PRESSED:
stk_sound_play( gui_theme->click_sound );
case GUI_ACTIVATED:
case GUI_DEACTIVATED:
case GUI_BUTTON_RELEASED:
case GUI_CLICKED:
case GUI_FOCUS_IN:
case GUI_FOCUS_OUT:
gui_widget_draw( widget );
break;
}
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create a button that may contain an icon and a text. Both are
displayed centered.
====================================================================
*/
GuiWidget* gui_button_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
SDL_Surface *icon, int ix, int iy, int iw, int ih,
char *caption )
{
int offset, i;
GuiWidget *widget = gui_widget_create(
parent, GUI_BUTTON, x, y, width, height,
default_event_handler, user_event_handler );
/* events */
gui_widget_enable_event( widget, GUI_CLICKED );
/* basic surface */
/* four different states in a vertical order:
NORMAL: normal wallpaper + normal button frame
FOCUSED: focus wallpaper + normal button frame
CLICKED: focus wallpaper + clicked button frame
INACTIVE: grayed NORMAL
*/
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height * 4 );
/* NORMAL */
stk_surface_apply_wallpaper(
widget->surface, 0,0,-1,height,
gui_theme->button_wallpaper_normal, -1 );
SDL_SetColorKey( widget->surface, 0,0 );
widget->border = stk_surface_apply_frame(
widget->surface, 0,0,-1,height,
gui_theme->button_frame_normal );
/* FOCUSED */
stk_surface_apply_wallpaper(
widget->surface, 0,height,-1,height,
gui_theme->button_wallpaper_focused, -1 );
stk_surface_apply_frame(
widget->surface, 0,height,-1,height,
gui_theme->button_frame_normal );
/* CLICKED */
stk_surface_apply_wallpaper(
widget->surface,
widget->border, widget->border + 2 * height,
-1,height,
gui_theme->button_wallpaper_focused, -1 );
stk_surface_apply_frame(
widget->surface, 0,2*height,-1,height,
gui_theme->button_frame_clicked );
/* INACTIVE */
stk_surface_apply_wallpaper(
widget->surface, 0,height*3,-1,height,
gui_theme->button_wallpaper_normal, -1 );
stk_surface_apply_frame(
widget->surface, 0,height*3,-1,height,
gui_theme->button_frame_normal );
stk_surface_gray( widget->surface,
0, height*3, width, height, 0 );
/* size w/o border */
widget->width -= 2 * widget->border;
widget->height -= 2 * widget->border;
/* add label and icon */
offset = width;
if ( icon )
offset -= iw;
if ( caption )
offset -= stk_font_string_width(
gui_theme->button_font, caption );
offset /= 2;
/* icon */
if ( icon ) {
for ( i = 0; i < 4; i++ )
stk_surface_alpha_blit( icon, ix, iy, iw, ih,
widget->surface,
offset + (i==2)*widget->border/2,
i * height + (height - ih) / 2 +
(i==2)*widget->border/2,
(i==3)?128:SDL_ALPHA_OPAQUE );
offset += iw;
}
if ( caption ) {
gui_theme->button_font->align = STK_FONT_ALIGN_CENTER_Y;
for ( i = 0; i < 4; i++ )
stk_font_write( gui_theme->button_font,
widget->surface,
offset + (i==2)*widget->border/2,
i * height + height / 2 +
(i==2)*widget->border/2,
(i==3)?128:SDL_ALPHA_OPAQUE, caption );
}
/* done */
return widget;
}

View File

@@ -0,0 +1,33 @@
/***************************************************************************
gui_button.h - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_BUTTON_H
#define __GUI_BUTTON_H
/*
====================================================================
Create a button that may contain an icon and a text. Both are
displayed centered.
====================================================================
*/
GuiWidget* gui_button_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
SDL_Surface *icon, int ix, int iy, int iw, int ih,
char *caption );
#endif

View File

@@ -0,0 +1,539 @@
/***************************************************************************
gui_edit.c - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "gui_widget.h"
#include "gui_edit.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
extern GuiWidget *gui_key_widget;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Global edit variables that are used by the focused widget and
are global as there is only one keyboard they can be related
with.
====================================================================
*/
static int gui_edit_blink_time = 0; /* used to toggle gui_edit_blink
twice a second */
static int gui_edit_blink = 0; /* if true a cursor is displayed at
the edit position */
static int gui_edit_delay = 0;
static int gui_edit_interval = 0; /* after a delay of 300 ms the
keyevent is repeated at an interval of 100 */
static int gui_edit_keysym = -1; /* last pressed keysym */
static int gui_edit_unicode = -1; /* last pressed unicode */
/* FORWARDED */
static void gui_edit_handle_key(
GuiWidget *widget, int keysym, int unicode );
static int gui_edit_adjust_cursor( GuiWidget *widget, int offset );
/*
====================================================================
Default event handler
====================================================================
*/
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
char *ptr;
int px, py, i;
switch ( event->type ) {
case GUI_DESTROY:
if ( widget->spec.edit.buffer )
free( widget->spec.edit.buffer );
if ( widget->spec.edit.display_buffer )
free( widget->spec.edit.display_buffer );
break;
case GUI_DRAW:
/* display surface */
stk_surface_blit(
widget->surface, 0, 0, -1, -1,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
/* add text */
gui_theme->edit_font->align = STK_FONT_ALIGN_LEFT;
ptr = widget->spec.edit.display_buffer;
px = widget->screen_region.x + widget->border;
py = widget->screen_region.y + widget->border +
widget->spec.edit.y_offset;
for ( i = 0; i < widget->spec.edit.height;
i++, py += gui_theme->edit_font->height,
ptr += widget->spec.edit.width + 1 )
stk_font_write( gui_theme->edit_font,
stk_display, px, py, -1, ptr );
/* add cursor */
if ( widget == gui_key_widget || widget->focused )
if ( gui_edit_blink )
stk_surface_fill( stk_display,
px + widget->spec.edit.x *
gui_theme->edit_font->width,
widget->screen_region.y +
widget->border + widget->spec.edit.y_offset +
widget->spec.edit.y *
gui_theme->edit_font->height,
1, gui_theme->edit_font->height,
0xffffff );
break;
case GUI_KEY_PRESSED:
if ( gui_edit_keysym != event->key.keysym ) {
gui_edit_delay = 250;
gui_edit_handle_key( widget,
event->key.keysym,
event->key.unicode );
//stk_sound_play( gui_theme->type_sound );
}
break;
case GUI_KEY_RELEASED:
gui_edit_keysym = -1;
break;
case GUI_FOCUS_OUT:
gui_edit_blink = 0;
gui_widget_draw( widget );
break;
case GUI_CLICKED:
stk_sound_play( gui_theme->click_sound );
px = event->button.x - widget->screen_region.x -
widget->border;
py = event->button.y - widget->screen_region.y -
widget->border - widget->spec.edit.y_offset;
gui_edit_adjust_cursor( widget,
(py / gui_theme->edit_font->height) *
widget->spec.edit.width +
(px / gui_theme->edit_font->width) +
widget->spec.edit.start - widget->spec.edit.pos + 1 );
gui_edit_blink = 1;
gui_edit_blink_time = 0;
gui_widget_draw( widget );
break;
}
}
/*
====================================================================
Render the display buffer from the edit string and the first
character displayed of it. No screen update.
====================================================================
*/
static void gui_edit_update_display_buffer( GuiWidget *widget )
{
int i, length, left;
char *src, *dest;
memset( widget->spec.edit.display_buffer, 0,
(widget->spec.edit.width+1) * widget->spec.edit.height *
sizeof( char ) );
if ( widget->spec.edit.multi_line ) {
src = widget->spec.edit.buffer + widget->spec.edit.start;
left = strlen( src );
dest = widget->spec.edit.display_buffer;
for ( i = 0; i < widget->spec.edit.height; i++ ) {
length = widget->spec.edit.width;
if ( length > left )
length = left;
strncpy( dest, src, length );
dest += widget->spec.edit.width + 1;
src += length;
left -= length;
if ( left == 0 )
break;
}
}
else {
strncpy( widget->spec.edit.display_buffer,
widget->spec.edit.buffer + widget->spec.edit.start,
widget->spec.edit.width );
}
}
/*
====================================================================
Adjust edit cursor position by offset and return True
if the display buffer has changed. Do not update display.
====================================================================
*/
static int gui_edit_adjust_cursor( GuiWidget *widget, int offset )
{
int new_y, changed = 0;
/* adjust position */
widget->spec.edit.pos += offset;
if ( widget->spec.edit.pos < 0 ) widget->spec.edit.pos = 0;
if ( widget->spec.edit.pos > widget->spec.edit.length )
widget->spec.edit.pos = widget->spec.edit.length;
/* don't blink cursor while moving */
gui_edit_blink_time = 0;
/* update display position */
if ( widget->spec.edit.multi_line ) {
new_y = widget->spec.edit.pos / widget->spec.edit.width;
/* if this position is out of screen modify 'line'
and 'start' */
if ( new_y < widget->spec.edit.line ||
new_y >= widget->spec.edit.line + widget->spec.edit.height ) {
if ( new_y < widget->spec.edit.line )
widget->spec.edit.line = new_y;
else
widget->spec.edit.line = new_y - widget->spec.edit.height + 1;
widget->spec.edit.start =
widget->spec.edit.line * widget->spec.edit.width;
/* update the display buffer */
gui_edit_update_display_buffer( widget );
changed = 1;
}
widget->spec.edit.x =
widget->spec.edit.pos % widget->spec.edit.width;
widget->spec.edit.y = new_y - widget->spec.edit.line;
}
else {
if ( widget->spec.edit.pos < widget->spec.edit.start ) {
widget->spec.edit.start = widget->spec.edit.pos;
widget->spec.edit.x = 0;
/* update the display buffer */
gui_edit_update_display_buffer( widget );
changed = 1;
}
else
if ( widget->spec.edit.pos >=
widget->spec.edit.start + widget->spec.edit.width ) {
widget->spec.edit.start = widget->spec.edit.pos -
widget->spec.edit.width;
widget->spec.edit.x = widget->spec.edit.width;
/* update the display buffer */
gui_edit_update_display_buffer( widget );
changed = 1;
}
else {
/* within text */
widget->spec.edit.x =
widget->spec.edit.pos - widget->spec.edit.start;
}
}
return changed;
}
/*
====================================================================
Handle the pressed key, modify the edit buffer and update the
displayed edit if visible.
====================================================================
*/
static void gui_edit_handle_key(
GuiWidget *widget, int keysym, int unicode )
{
int i, changed = 0, old_length = widget->spec.edit.length;
switch ( keysym ) {
case SDLK_RIGHT:
gui_edit_adjust_cursor( widget, 1 );
changed = 1;
break;
case SDLK_LEFT:
gui_edit_adjust_cursor( widget, -1 );
changed = 1;
break;
case SDLK_DOWN:
gui_edit_adjust_cursor(
widget, widget->spec.edit.width );
changed = 1;
break;
case SDLK_UP:
gui_edit_adjust_cursor(
widget, -widget->spec.edit.width );
changed = 1;
break;
case SDLK_HOME:
gui_edit_adjust_cursor(
widget, -widget->spec.edit.pos );
changed = 1;
break;
case SDLK_END:
widget->spec.edit.pos = 0;
gui_edit_adjust_cursor(
widget, widget->spec.edit.length );
changed = 1;
break;
case SDLK_BACKSPACE:
if ( widget->spec.edit.pos > 0 ) {
--widget->spec.edit.pos;
for ( i = widget->spec.edit.pos;
i < widget->spec.edit.length - 1; i++ )
widget->spec.edit.buffer[i] =
widget->spec.edit.buffer[i + 1];
widget->spec.edit.buffer[i] = 0;
widget->spec.edit.length--;
if ( !gui_edit_adjust_cursor( widget, 0 ) )
gui_edit_update_display_buffer( widget );
changed = 1;
}
break;
case SDLK_DELETE:
if ( widget->spec.edit.pos < widget->spec.edit.length ) {
for ( i = widget->spec.edit.pos;
i < widget->spec.edit.length - 1; i++ )
widget->spec.edit.buffer[i] =
widget->spec.edit.buffer[i + 1];
widget->spec.edit.buffer[i] = 0;
widget->spec.edit.length--;
gui_edit_update_display_buffer( widget );
changed = 1;
}
break;
default:
if ( widget->spec.edit.filter[unicode] && widget->spec.edit.pos < widget->spec.edit.size )
if ( widget->spec.edit.length < widget->spec.edit.size ) {
for ( i = widget->spec.edit.size - 1;
i > widget->spec.edit.pos; i-- )
widget->spec.edit.buffer[i] =
widget->spec.edit.buffer[i - 1];
widget->spec.edit.buffer[widget->spec.edit.pos++] = unicode;
widget->spec.edit.length++;
if ( !gui_edit_adjust_cursor( widget, 0 ) )
gui_edit_update_display_buffer( widget );
changed = 1;
}
break;
}
if ( changed ) {
gui_edit_blink_time = 0;
gui_edit_blink = 1;
gui_widget_draw( widget );
gui_edit_interval = 0;
gui_edit_keysym = keysym;
gui_edit_unicode = unicode;
if ( old_length != widget->spec.edit.length ) {
gui_widget_call_user_event_handler(
widget, gui_event_get_simple( GUI_CHANGED ) );
}
}
else
gui_edit_keysym = -1;
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create a multi-line editable widget. By checking the measurements
of the standard font the number of lines and the line width is
determined.
'text': is copied and displayed when first shown
'size': limit of characters (excluding the \0)
====================================================================
*/
GuiWidget* gui_edit_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int border, int multi_line, int size, char *text )
{
GuiWidget *widget = gui_widget_create(
parent, GUI_EDIT, x, y, width, height,
default_event_handler, user_event_handler );
/* events */
gui_widget_enable_event( widget, GUI_CHANGED );
/* create surface, wallpaper and frame it */
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height );
SDL_SetColorKey( widget->surface, 0,0 );
stk_surface_apply_wallpaper( widget->surface, 0,0,-1,-1,
gui_theme->widget_wallpaper, STK_OPAQUE );
widget->border = stk_surface_apply_frame(
widget->surface, 0, 0, -1, -1,
gui_theme->widget_frame );
/* size w/o border */
widget->width -= 2 * widget->border;
widget->height -= 2 * widget->border;
/* grab keys */
widget->grab_keys = 1;
/* prepare text */
gui_edit_set_filter( widget, GUI_EDIT_DEFAULT );
widget->spec.edit.multi_line = multi_line;
widget->border += border;
widget->spec.edit.width =
(width - widget->border*2) /
gui_theme->edit_font->width;
if ( multi_line )
widget->spec.edit.height =
(height - widget->border*2) /
gui_theme->edit_font->height;
else
widget->spec.edit.height = 1;
widget->spec.edit.display_buffer =
calloc( (widget->spec.edit.width+1) * widget->spec.edit.height,
sizeof( char ) );
if ( widget->spec.edit.display_buffer == 0 )
GUI_ABORT( "Out Of Memory" );
gui_edit_resize_buffer( widget, size );
gui_edit_set_text( widget, text );
/* center single-line edit */
if ( !multi_line )
widget->spec.edit.y_offset =
(height - 2 * widget->border -
gui_theme->edit_font->height) / 2;
/* done */
return widget;
}
/*
====================================================================
Resize the edit buffer and clear any text. (no update)
====================================================================
*/
void gui_edit_resize_buffer( GuiWidget *widget, int size )
{
if ( widget->type != GUI_EDIT ) return;
widget->spec.edit.size = size;
if ( widget->spec.edit.buffer )
free( widget->spec.edit.buffer );
widget->spec.edit.buffer = calloc( size + 1, sizeof( char ) );
if ( widget->spec.edit.buffer == 0 )
GUI_ABORT( "Out Of Memory" );
}
/*
====================================================================
Set the edit's text. This resets the edit cursor's position to
end of text and updates displayed edit if visible.
====================================================================
*/
void gui_edit_set_text( GuiWidget *widget, char *text )
{
if ( widget->type != GUI_EDIT ) return;
/* copy text */
snprintf( widget->spec.edit.buffer, widget->spec.edit.size + 1, "%s", text );
widget->spec.edit.length = strlen( widget->spec.edit.buffer );
/* reset */
/* first character in first line */
widget->spec.edit.pos = 0;
widget->spec.edit.x = widget->spec.edit.y = 0;
widget->spec.edit.start = widget->spec.edit.line = 0;
/* jump to end */
if ( !gui_edit_adjust_cursor( widget, widget->spec.edit.length ) )
gui_edit_update_display_buffer( widget );
/* update */
if ( widget->visible )
gui_widget_draw( widget );
}
/*
====================================================================
Copy characters from 'start' to 'length' of the edit string to
'buffer' (at maximum limit characters including \0). If 'length'
is -1 the characters copied are those from 'start' to end of text.
====================================================================
*/
int gui_edit_get_text(
GuiWidget *widget, char *buffer, int limit,
int start, int length )
{
char *ptr;
if ( widget->type != GUI_EDIT ) return 0;
if ( start < 0 ) start = 0;
ptr = widget->spec.edit.buffer + start;
if ( length == -1 )
length = strlen( ptr );
if ( length > limit )
length = limit;
if ( length )
snprintf( buffer, limit, "%s", widget->spec.edit.buffer );
else
buffer[0] = 0;
return 1;
}
/*
====================================================================
Update the blinking cursor flag (no update) of the edit and in
case a key is pressed call gui_edit_handle_key().
====================================================================
*/
void gui_edit_update( GuiWidget *widget, int ms )
{
gui_edit_blink_time += ms;
if ( gui_edit_blink_time > 500 ) {
gui_edit_blink_time = 0;
gui_edit_blink = !gui_edit_blink;
gui_widget_draw( widget );
}
if ( gui_edit_keysym != -1 ) {
if ( gui_edit_delay > 0 ) {
gui_edit_delay -= ms;
if ( gui_edit_delay <= 0 )
gui_edit_delay = 0;
}
if ( gui_edit_delay == 0 ) {
if ( gui_edit_interval > 0 ) {
gui_edit_interval -= ms;
if ( gui_edit_interval < 0 )
gui_edit_interval = 0;
}
if ( gui_edit_interval == 0 ) {
gui_edit_handle_key( widget,
gui_edit_keysym, gui_edit_unicode );
gui_edit_interval = 30;
}
}
}
}
/*
====================================================================
Select a character set.
default: all non-whitespaces >=32 && <= 128
alpha: A-Z,a-z
numerical: 0-9
alphanumerical: A-Z,a-z,0-9
====================================================================
*/
void gui_edit_set_filter( GuiWidget *widget, int type )
{
int i, j;
if ( widget->type != GUI_EDIT ) return;
memset( widget->spec.edit.filter, 0,
sizeof( widget->spec.edit.filter ) );
switch ( type ) {
case GUI_EDIT_DEFAULT:
for ( i = 32; i <= 128; i++ )
widget->spec.edit.filter[i] = 1;
break;
case GUI_EDIT_ALPHANUMERICAL:
case GUI_EDIT_ALPHANUMERICAL2:
case GUI_EDIT_ALPHA:
for ( i = 65, j = 97; i <= 90; i++, j++ ) {
widget->spec.edit.filter[i] = 1;
widget->spec.edit.filter[j] = 1;
}
if ( type == GUI_EDIT_ALPHANUMERICAL || type == GUI_EDIT_ALPHANUMERICAL2 ) {
widget->spec.edit.filter[45] = 1;
for ( i = 48; i <= 57; i++ )
widget->spec.edit.filter[i] = 1;
}
if ( type == GUI_EDIT_ALPHANUMERICAL2 )
widget->spec.edit.filter[95] = 1;
break;
case GUI_EDIT_NUMERICAL:
for ( i = 48; i <= 57; i++ )
widget->spec.edit.filter[i] = 1;
widget->spec.edit.filter[45] = 1;
break;
}
}

View File

@@ -0,0 +1,87 @@
/***************************************************************************
gui_edit.h - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_EDIT_H
#define __GUI_EDIT_H
/*
====================================================================
Create a single/multi-line editable widget. By checking the
measurements of the standard font the number of lines and the
line width is determined. If the edit is single-lined height is
always one but edit becomes scrollable.
'border': between text and frame
'text': is copied and displayed when first shown
'size': limit of characters (excluding the \0)
Per default the edit accepts all non-whitespace characters.
====================================================================
*/
GuiWidget* gui_edit_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int border, int multi_line, int size, char *text );
/*
====================================================================
Resize the edit buffer and clear any text. (no update)
====================================================================
*/
void gui_edit_resize_buffer( GuiWidget *edit, int size );
/*
====================================================================
Set the edit's text. This resets the edit cursor's position to
end of text and updates displayed edit if visible.
====================================================================
*/
void gui_edit_set_text( GuiWidget *edit, char *text );
/*
====================================================================
Copy characters from 'start' to 'length' of the edit string to
'buffer' (at maximum limit characters including \0). If 'length' is
-1 the characters copied are those from 'start' to end of text.
====================================================================
*/
int gui_edit_get_text(
GuiWidget *edit, char *buffer, int limit,
int start, int length );
/*
====================================================================
Update the blinking cursor flag (no update) of the edit and in
case a key is pressed call gui_edit_handle_key().
====================================================================
*/
void gui_edit_update( GuiWidget *widget, int ms );
/*
====================================================================
Select a character filter.
default: all non-whitespaces >=32 && <= 128
alpha: A-Z,a-z
numerical: -,0-9
alphanumerical: A-Z,a-z,0-9
alphanumerical2: + underscores
====================================================================
*/
enum {
GUI_EDIT_DEFAULT = 0,
GUI_EDIT_ALPHA,
GUI_EDIT_NUMERICAL,
GUI_EDIT_ALPHANUMERICAL,
GUI_EDIT_ALPHANUMERICAL2
};
void gui_edit_set_filter( GuiWidget *edit, int type );
#endif

View File

@@ -0,0 +1,119 @@
/***************************************************************************
gui_icon.c - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include "gui_widget.h"
#include "gui_icon.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Default event handler
====================================================================
*/
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
switch ( event->type ) {
case GUI_DESTROY:
break;
case GUI_DRAW:
/* display surface */
stk_surface_blit(
widget->surface, 0, 0, -1, -1,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
break;
}
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create an icon widget that displays the icon centered and uses
the parent's background.
====================================================================
*/
GuiWidget *gui_icon_create(
GuiWidget *parent, int x, int y, int width, int height, int with_frame,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
SDL_Surface *icon, int ix, int iy, int iw, int ih )
{
GuiWidget *widget = gui_widget_create(
parent, GUI_ICON, x, y, width, height,
default_event_handler, user_event_handler );
/* events */
gui_widget_enable_event( widget, GUI_CLICKED );
/* create surface and add frame -
contents is set by icon_set_icon() */
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height );
if ( with_frame )
widget->border = stk_surface_apply_frame(
widget->surface, 0, 0, -1, -1,
gui_theme->widget_frame );
/* size w/o border */
widget->width -= 2 * widget->border;
widget->height -= 2 * widget->border;
/* set icon */
gui_icon_set_icon( widget, icon, ix, iy, iw, ih );
/* done */
return widget;
}
/*
====================================================================
Apply a new icon.
====================================================================
*/
void gui_icon_set_icon(
GuiWidget *widget, SDL_Surface *icon,
int ix, int iy, int iw, int ih )
{
if ( widget->type != GUI_ICON ) return;
/* clear widget to wallpaper */
gui_widget_apply_wallpaper(
widget, gui_theme->widget_wallpaper, -1 );
/* add icon */
if ( icon ) {
/* adjust size */
if ( iw == -1 ) iw = icon->w;
if ( ih == -1 ) ih = icon->h;
stk_surface_blit( icon, ix, iy, iw, ih,
widget->surface,
(widget->surface->w - iw)/2,
(widget->surface->h - ih)/2 );
}
/* done */
if ( widget->visible )
gui_widget_draw( widget );
}

View File

@@ -0,0 +1,43 @@
/***************************************************************************
gui_icon.h - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_ICON_H
#define __GUI_ICON_H
/*
====================================================================
Create an icon widget that displays the icon centered and uses
the parent's background.
====================================================================
*/
GuiWidget *gui_icon_create(
GuiWidget *parent, int x, int y, int width, int height,
int with_frame,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
SDL_Surface *icon, int ix, int iy, int iw, int ih );
/*
====================================================================
Apply a new icon.
====================================================================
*/
void gui_icon_set_icon(
GuiWidget *icon, SDL_Surface *source,
int ix, int iy, int iw, int ih );
#endif

View File

@@ -0,0 +1,276 @@
/***************************************************************************
gui_label.c - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "gui_widget.h"
#include "gui_label.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Convert a text string into single lines of maximum length
'char_width'.
====================================================================
*/
typedef struct {
char **lines;
int count;
} LabelText;
static void repl_new_lines( char *text )
{
int i;
for ( i = 0; i < strlen( text ); i++ )
if ( text[i] < 32 )
text[i] = 32;
}
static LabelText* text_create( char *orig_str, int char_width )
{
int i, j;
char line[256]; /* a line should not exceed this length */
int pos;
int last_space;
int new_line;
LabelText *text = 0;
char *str = 0;
text = calloc ( 1, sizeof( LabelText ) );
/* maybe orig_str is a constant expression; duplicate for safety */
str = strdup( orig_str );
/* replace original new_lines with spaces */
repl_new_lines( str );
/* change some spaces to new_lines, so that the new text fits the wanted line_length */
/* NOTE: '#' means new_line ! */
// if character with is 0 it's just a single line //
if ( char_width > 0 ) {
pos = 0;
while ( pos < strlen( str ) ) {
last_space = 0;
new_line = 0;
i = 0;
while ( !new_line && i < char_width && i + pos < strlen( str ) ) {
switch ( str[pos + i] ) {
case '#': new_line = 1;
case 32: last_space = i; break;
}
i++;
}
if ( i + pos >= strlen( str ) ) break;
if ( last_space == 0 ) {
/* uhh... much to long, we'll have to cut a word into pieces ... */
last_space = char_width / 2;
}
str[pos + last_space] = 10;
pos += last_space;
}
}
/* count lines */
if ( char_width > 0 ) {
for ( i = 0; i < strlen( str ); i++ )
if ( str[i] == 10 )
text->count++;
/* maybe one unfinished line */
if ( str[strlen( str ) - 1] != 10 )
text->count++;
}
else
text->count = 1;
/* get mem */
text->lines = calloc( text->count, sizeof( char* ) );
/* get all lines */
pos = 0;
for ( j = 0; j < text->count; j++ ) {
i = 0;
while ( pos + i < strlen( str ) && str[pos + i] != 10 ) {
line[i] = str[i + pos];
i++;
}
pos += i; pos++;
line[i] = 0;
text->lines[j] = strdup( line );
}
if ( text->count == 0 )
fprintf( stderr, "conv_to_text: warning: line_count is 0\n" );
free( str );
return text;
}
static void text_delete( LabelText *text )
{
int i;
if ( text == 0 ) return;
if ( text->lines ) {
for ( i = 0; i < text->count; i++ )
if ( text->lines[i] )
free( text->lines[i] );
free( text->lines );
}
free( text );
}
/*
====================================================================
Default event handler
====================================================================
*/
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
switch ( event->type ) {
case GUI_DESTROY:
if ( widget->spec.label.text )
free( widget->spec.label.text );
break;
case GUI_DRAW:
/* display surface */
stk_surface_blit(
widget->surface, 0, 0, -1, -1,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
break;
}
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create a label widget with the parent's background and maybe a
frame.
'border': space between text and frame
'text': text that may contain multiple lines separated by '#'
(duplicated)
'align': alignment for each line
'font': used to display the text. if NULL is passed the default
label font is used
====================================================================
*/
GuiWidget* gui_label_create(
GuiWidget *parent, int x, int y, int width, int height, int with_frame,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int border, StkFont *font, int align, char *text )
{
GuiWidget *widget = gui_widget_create(
parent, GUI_LABEL, x, y, width, height,
default_event_handler, user_event_handler );
/* events */
gui_widget_enable_event( widget, GUI_CLICKED );
/* create surface and add frame -
contents is set by label_set_text() */
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height );
SDL_SetColorKey( widget->surface, 0,0 );
if ( with_frame )
widget->border = stk_surface_apply_frame(
widget->surface, 0, 0, -1, -1,
gui_theme->widget_frame );
/* add some extra space between frame and text */
widget->border += border;
/* size w/o border */
widget->width -= 2 * widget->border;
widget->height -= 2 * widget->border;
/* set font and alignment */
widget->spec.label.font = (font)?font:gui_theme->label_font;
widget->spec.label.align = align;
/* do the text */
if ( text )
widget->spec.label.text = strdup( text );
gui_label_set_text( widget, text );
/* done */
return widget;
}
/*
====================================================================
Set label font/alignment/text. Update if visible.
====================================================================
*/
void gui_label_set_font( GuiWidget *widget, StkFont *font )
{
if ( widget->type != GUI_LABEL ) return;
widget->spec.label.font = font;
gui_label_set_text( widget, widget->spec.label.text );
}
void gui_label_set_align( GuiWidget *widget, int align )
{
if ( widget->type != GUI_LABEL ) return;
widget->spec.label.align = align;
gui_label_set_text( widget, widget->spec.label.text );
}
static char label_buffer[1024];
void gui_label_set_text( GuiWidget *widget, char *format, ... )
{
LabelText *text;
int px, py, i;
va_list args;
if ( widget->type != GUI_LABEL ) return;
/* free old text */
if ( widget->spec.label.text ) {
free( widget->spec.label.text );
widget->spec.label.text = 0;
}
/* clear widget to wallpaper */
gui_widget_apply_wallpaper(
widget, gui_theme->widget_wallpaper, -1 );
/* set new text if any */
if ( format ) {
/* build full string */
va_start( args, format );
vsnprintf( label_buffer, 1024, format, args );
va_end( args );
/* build text */
widget->spec.label.text = strdup( label_buffer );
text = text_create( widget->spec.label.text,
(widget->screen_region.w - 2 * widget->border) /
widget->spec.label.font->width );
/* add text */
widget->spec.label.font->align = widget->spec.label.align;
if ( widget->spec.label.align & STK_FONT_ALIGN_LEFT )
px = widget->border;
else
if ( widget->spec.label.align & STK_FONT_ALIGN_RIGHT )
px = widget->screen_region.w - widget->border;
else
px = widget->border +
((widget->screen_region.w -
(widget->border<<1))>>1);
py = (widget->parent_region.h -
text->count * widget->spec.label.font->height) / 2;
for ( i = 0; i < text->count;
i++, py += widget->spec.label.font->height )
stk_font_write( widget->spec.label.font,
widget->surface, px, py, -1,
text->lines[i] );
text_delete( text );
}
/* display */
if ( widget->visible )
gui_widget_draw( widget );
}

View File

@@ -0,0 +1,48 @@
/***************************************************************************
gui_label.h - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_LABEL_H
#define __GUI_LABEL_H
/*
====================================================================
Create a label widget with the parent's background and maybe a
frame.
'border': space between text and frame
'text': text that may contain multiple lines separated by '#'
(duplicated)
'align': alignment for each line
'font': used to display the text. if NULL is passed the default
label font is used
====================================================================
*/
GuiWidget* gui_label_create(
GuiWidget *parent, int x, int y, int width, int height,
int with_frame,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int border, StkFont *font, int align, char *text );
/*
====================================================================
Set label font/alignment/text. Update if visible.
====================================================================
*/
void gui_label_set_font( GuiWidget *label, StkFont *font );
void gui_label_set_align( GuiWidget *label, int align );
void gui_label_set_text( GuiWidget *label, char *format, ... );
#endif

View File

@@ -0,0 +1,412 @@
/***************************************************************************
gui_list.c - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include "gui_widget.h"
#include "gui_button.h"
#include "gui_scrollbar.h"
#include "gui_list.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Default event handler
====================================================================
*/
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
Uint32 color;
SDL_Rect rect;
int pos, px, py, item_id, i, j;
switch ( event->type ) {
case GUI_DESTROY:
if ( widget->spec.list.checks )
free( widget->spec.list.checks );
stk_surface_free( &widget->spec.list.render_buffer );
break;
case GUI_DRAW:
/* display surface */
stk_surface_blit(
widget->surface, 0, 0, -1, -1,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
/* render items */
if ( widget->spec.list.item_count == 0 )
break;
pos = 0;
if ( widget->spec.list.scrollbar )
gui_scrollbar_get_value(
widget->spec.list.scrollbar, &pos );
item_id = pos * widget->spec.list.columns;
py = widget->screen_region.y + widget->border;
for ( j = 0; j < widget->spec.list.rows_per_page; j++ ) {
px = widget->screen_region.x + widget->border;
for ( i = 0; i < widget->spec.list.columns; i++ ) {
if ( (widget->spec.list.select_type ==
GUI_LIST_SINGLE_SELECT &&
widget->spec.list.checks[0] == item_id) ||
(widget->spec.list.select_type ==
GUI_LIST_MULTI_SELECT &&
widget->spec.list.checks[item_id] ) ) {
color = stk_surface_get_pixel(
gui_theme->list_item_color, 0, 0 );
SDL_FillRect(
widget->spec.list.render_buffer, 0, color );
stk_surface_alpha_blit( widget->surface,
px - widget->screen_region.x,
py - widget->screen_region.y,
widget->spec.list.item_width,
widget->spec.list.item_height,
widget->spec.list.render_buffer, 0, 0,
192 );
}
else
stk_surface_fill(
widget->spec.list.render_buffer, 0,0,-1,-1,
0x0 );
if ( widget->spec.list.render_item(
i, j + pos, widget->spec.list.render_buffer ) )
stk_surface_blit(
widget->spec.list.render_buffer,
0,0,-1,-1, stk_display, px, py );
px += widget->spec.list.item_width +
widget->spec.list.gap;
item_id++;
if ( item_id >= widget->spec.list.item_count )
break;
}
py += widget->spec.list.item_height +
widget->spec.list.gap;
if ( item_id >= widget->spec.list.item_count )
break;
}
break;
case GUI_BUTTON_PRESSED:
if ( event->button.button == STK_WHEEL_UP )
gui_scrollbar_add( widget->spec.list.scrollbar,
-widget->spec.list.scrollbar->spec.scrollbar.step*2 );
else
if ( event->button.button == STK_WHEEL_DOWN )
gui_scrollbar_add( widget->spec.list.scrollbar,
widget->spec.list.scrollbar->spec.scrollbar.step*2 );
else {
/* handle selection */
pos = 0;
if ( widget->spec.list.scrollbar )
gui_scrollbar_get_value(
widget->spec.list.scrollbar, &pos );
rect.w = widget->spec.list.item_width;
rect.h = widget->spec.list.item_height;
rect.y = widget->screen_region.y +
widget->border;
for ( j = 0; j < widget->spec.list.rows_per_page; j++ ) {
rect.x = widget->screen_region.x +
widget->border;
for ( i = 0; i < widget->spec.list.columns; i++ ) {
if ( STK_IN_RECT( rect,
event->button.x,
event->button.y ) ) {
gui_list_select(
widget, i, j + pos, -1 );
return;
}
rect.x += widget->spec.list.item_width +
widget->spec.list.gap;
}
rect.y += widget->spec.list.item_height +
widget->spec.list.gap;
}
}
break;
}
}
/*
====================================================================
Dummy routine to produce an empty list.
====================================================================
*/
static int gui_list_render_item_dummy(
int x, int y, SDL_Surface *buffer )
{
return 0;
}
/*
====================================================================
Default handler for listbox scrollbar.
====================================================================
*/
static void gui_list_scrollbar_handler(
GuiWidget *widget, GuiEvent *event )
{
/* update the listbox */
if ( event->type == GUI_CHANGED )
gui_widget_draw( widget->parent );
/* call event handler */
gui_widget_call_user_event_handler( widget->parent, event );
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create a listbox that may have multiple columns which cannot be
scrolled however.
'gap': gap between items and frame
'columns': the item width is determined by available_width/columns
'item_height': the number of rows is unlimited and this is the
height of an item
'scrollbar_width' : if > 0 a vertical scrollbar is provided
'render_item': The scrollbar value (0 if none) tells which row
is the first displayed and
render_item(row,column,buffer) is called to
obtain the graphic for each visible item.
If 'render_item' returns False the item is not
displayed.
'select_type': no, single, multi select
====================================================================
*/
GuiWidget* gui_list_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int gap, int columns, int item_height,
int scrollbar_width, int (*render_item)(int,int,SDL_Surface*),
int select_type )
{
int old_border;
GuiWidget *widget = gui_widget_create(
parent, GUI_LIST, x, y, width, height,
default_event_handler, user_event_handler );
/* events */
gui_widget_enable_event( widget, GUI_ITEM_SELECTED );
gui_widget_enable_event( widget, GUI_ITEM_UNSELECTED );
/* create surface and wallpaper it */
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height );
SDL_SetColorKey( widget->surface, 0,0 );
stk_surface_apply_wallpaper(
widget->surface, 0, 0, -1, -1,
gui_theme->widget_wallpaper, -1 );
/* add frame leaving space for scrollbar */
widget->border = stk_surface_apply_frame(
widget->surface, 0, 0, width - scrollbar_width, height,
gui_theme->widget_frame );
/* size w/o border */
widget->width -= 2 * widget->border;
widget->height -= 2 * widget->border;
/* distance between frame and items */
widget->spec.list.gap = gap;
widget->border += gap;
/* item settings */
widget->spec.list.columns = columns;
widget->spec.list.item_width =
(width - scrollbar_width - widget->border*2 + gap) /
columns - gap;
widget->spec.list.item_height = item_height;
widget->spec.list.rows_per_page =
(height - widget->border*2 + gap) / (item_height + gap);
/* selection */
widget->spec.list.select_type = select_type;
widget->spec.list.checks = calloc( 1, sizeof( int ) );
if ( widget->spec.list.checks == 0 )
GUI_ABORT( "Out Of Memory" );
/* render callback */
if ( render_item == 0 ) {
fprintf( stderr,
"You must specify a render callback for lists!\n" );
widget->spec.list.render_item = gui_list_render_item_dummy;
}
else
widget->spec.list.render_item = render_item;
/* build scrollbar if any */
if ( scrollbar_width > 0 ) {
/* the border is set to 0 as the frame doesn't
apply to the scrollbar */
old_border = widget->border;
widget->border = 0;
widget->spec.list.scrollbar = gui_scrollbar_create( widget,
width - scrollbar_width, 0, scrollbar_width, height,
gui_list_scrollbar_handler, 1,
0, 0, 1, widget->spec.list.rows_per_page / 2, 0 );
widget->border = old_border;
gui_widget_disable_event( widget->spec.list.scrollbar, GUI_FOCUS_IN );
gui_widget_disable_event( widget->spec.list.scrollbar, GUI_FOCUS_OUT );
}
/* create the render buffer */
widget->spec.list.render_buffer =
stk_surface_create( SDL_SWSURFACE,
widget->spec.list.item_width, widget->spec.list.item_height );
if ( widget->spec.list.render_buffer == 0 )
GUI_ABORT( "Out Of Memory" );
return widget;
}
/*
====================================================================
Set item count of list and update it even if item count hasn't
changed. This function is used to tell the list that it
contents has changed and needs to be redrawn. All selections
are cleared by this function.
====================================================================
*/
void gui_list_update( GuiWidget *widget, int count )
{
int value = 0, old_count = widget->spec.list.item_count;
if ( widget->type != GUI_LIST ) return;
/* adjust count and row number */
widget->spec.list.item_count = count;
widget->spec.list.rows =
widget->spec.list.item_count / widget->spec.list.columns +
((widget->spec.list.item_count %
widget->spec.list.columns) != 0);
/* clear checks */
if ( widget->spec.list.select_type == GUI_LIST_MULTI_SELECT ) {
free( widget->spec.list.checks );
widget->spec.list.checks =
calloc( (count<=0)?1:count, sizeof( int ) );
}
else
widget->spec.list.checks[0] = -1;
/* set range and value of scrollbar */
if ( widget->spec.list.scrollbar ) {
if ( count > old_count ) {
/* additional items. current scrollbar value will
still be valid. no screen update yet. */
if ( widget->visible )
widget->spec.list.scrollbar->
spec.scrollbar.track->visible = 0;
value = widget->spec.list.rows -
widget->spec.list.rows_per_page;
if ( value < 0 ) value = 0;
gui_scrollbar_set_range(
widget->spec.list.scrollbar, 0, value, -1, -1 );
if ( widget->visible )
widget->spec.list.scrollbar->
spec.scrollbar.track->visible = 1;
}
else if ( count < old_count ) {
/* lesser items. the current scrollbar value
may be out of range. no screen update yet. */
gui_scrollbar_get_value(
widget->spec.list.scrollbar, &value );
if ( widget->visible )
widget->spec.list.scrollbar->
spec.scrollbar.track->visible = 0;
value = widget->spec.list.rows -
widget->spec.list.rows_per_page;
if ( value < 0 ) value = 0;
if ( value + widget->spec.list.rows_per_page >
widget->spec.list.rows ) {
gui_scrollbar_set_value( widget->spec.list.scrollbar,
value );
}
gui_scrollbar_set_range(
widget->spec.list.scrollbar, 0, value, -1, -1 );
if ( widget->visible )
widget->spec.list.scrollbar->
spec.scrollbar.track->visible = 1;
}
}
/* redraw */
if ( widget->visible )
gui_widget_draw( widget );
}
/*
====================================================================
Handle a listbox selection and update listbox.
If 'select' is 1 the item is selected, if it's 0 the item
is unselected, -1 means to toggle the value.
If SINGLE_SELECT toggeling the current selection keeps selection.
====================================================================
*/
void gui_list_select(
GuiWidget *widget, int column, int row, int select )
{
GuiEvent event;
int id, pos;
if ( widget->type != GUI_LIST ) return;
if ( widget->spec.list.select_type == GUI_LIST_NO_SELECT ) return;
event.type = GUI_NONE;
event.item.x = column;
event.item.y = row;
/* get id of item */
id = row * widget->spec.list.columns + column;
/* update selection */
if ( widget->spec.list.select_type == GUI_LIST_SINGLE_SELECT ) {
if ( select == 1 || select == -1 ) {
widget->spec.list.checks[0] = id;
event.type = GUI_ITEM_SELECTED;
}
else
if ( select == 0 && id == widget->spec.list.checks[0] ) {
widget->spec.list.checks[0] = -1;
event.type = GUI_ITEM_UNSELECTED;
}
}
else {
if ( select == -1 )
widget->spec.list.checks[id] = !widget->spec.list.checks[id];
else
widget->spec.list.checks[id] = select;
event.type = (widget->spec.list.checks[id]) ?
GUI_ITEM_SELECTED :
GUI_ITEM_UNSELECTED;
}
/* selection event? */
if ( event.type != GUI_NONE )
gui_widget_call_user_event_handler( widget, &event );
/* redraw */
if ( widget->visible ) {
pos = 0;
if ( widget->spec.list.scrollbar )
gui_scrollbar_get_value(
widget->spec.list.scrollbar, &pos );
if ( row >= pos )
if ( row < pos + widget->spec.list.rows_per_page )
gui_widget_draw( widget );
}
}
/*
====================================================================
Display passed row as first one or jump to end if 'row' is -1 .
====================================================================
*/
void gui_list_goto( GuiWidget *widget, int row )
{
if ( widget->type != GUI_LIST ) return;
if ( row == -1 )
gui_scrollbar_add( widget->spec.list.scrollbar,
widget->spec.list.item_count );
else
gui_scrollbar_add( widget->spec.list.scrollbar,
row - widget->spec.list.scrollbar->spec.scrollbar.value );
}

View File

@@ -0,0 +1,81 @@
/***************************************************************************
gui_list.h - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_LIST_H
#define __GUI_LIST_H
/* select types */
enum {
GUI_LIST_MULTI_SELECT = -1,
GUI_LIST_NO_SELECT,
GUI_LIST_SINGLE_SELECT
};
/*
====================================================================
Create a listbox that may have multiple columns which cannot be
scrolled however.
'gap': gap between items and frame
'columns': the item width is determined by available_width/columns
'item_height': the number of rows is unlimited and this is the
height of an item
'scrollbar_width' : if > 0 a vertical scrollbar is provided
'render_item': The scrollbar value (0 if none) tells which row
is the first displayed and
render_item(row,column,buffer) is called to
obtain the graphic for each visible item.
If 'render_item' returns False the item is not
displayed.
'select_type': no, single, multi select
====================================================================
*/
GuiWidget* gui_list_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int gap, int columns, int item_height,
int scrollbar_width, int (*render_item)(int,int,SDL_Surface*),
int select_type );
/*
====================================================================
Set item count of list and update it even if item count hasn't
changed. This function is used to tell the list that it
contents has changed and needs to be redrawn. All selections
are cleared by this function.
====================================================================
*/
void gui_list_update( GuiWidget *list, int count );
/*
====================================================================
Handle a listbox selection and update listbox.
If 'select' is 1 the item is selected, if it's 0 the item
is unselected, -1 means to toggle the value.
If SINGLE_SELECT toggeling the current selection keeps selection.
====================================================================
*/
void gui_list_select(
GuiWidget *list, int column, int row, int select );
/*
====================================================================
Display passed row as first one or jump to end if 'row' is -1 .
====================================================================
*/
void gui_list_goto( GuiWidget *list, int row );
#endif

View File

@@ -0,0 +1,186 @@
/***************************************************************************
gui_progressbar.c - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include "gui_widget.h"
#include "gui_progressbar.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Default event handler
====================================================================
*/
static char progressbar_hint[32];
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
switch ( event->type ) {
case GUI_DESTROY:
break;
case GUI_DRAW:
/* display surface */
stk_surface_blit(
widget->surface, 0,0,-1,-1,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
/* add progress */
stk_surface_apply_wallpaper( stk_display,
widget->screen_region.x + widget->border,
widget->screen_region.y + widget->border,
widget->spec.progressbar.length,
widget->screen_region.h - (widget->border<<1),
widget->spec.progressbar.wallpaper, -1 );
/* if focused add info */
if ( widget->focused ) {
gui_theme->progressbar_font->align =
STK_FONT_ALIGN_CENTER_X |
STK_FONT_ALIGN_CENTER_Y;
snprintf( progressbar_hint, 32, "%i/%i",
widget->spec.progressbar.value,
widget->spec.progressbar.max );
stk_font_write( gui_theme->progressbar_font,
stk_display,
widget->screen_region.x +
widget->screen_region.w/2,
widget->screen_region.y +
widget->screen_region.h/2,
-1, progressbar_hint );
}
break;
case GUI_FOCUS_IN:
case GUI_FOCUS_OUT:
gui_widget_draw( widget );
break;
}
}
/*
====================================================================
Adjust length of the beam and set correct beam wallpaper.
(no update)
====================================================================
*/
static void gui_progressbar_adjust( GuiWidget *widget )
{
int ratio = 100 * widget->spec.progressbar.value /
widget->spec.progressbar.max;
/* wallpaper */
if ( ratio > 60 )
widget->spec.progressbar.wallpaper =
gui_theme->progress_high;
else
if ( ratio > 25 )
widget->spec.progressbar.wallpaper =
gui_theme->progress_medium;
else
widget->spec.progressbar.wallpaper =
gui_theme->progress_low;
/* length */
widget->spec.progressbar.length =
(widget->parent_region.w - (widget->border<<1)) *
widget->spec.progressbar.value / widget->spec.progressbar.max;
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create a framed progress bar.
====================================================================
*/
GuiWidget *gui_progressbar_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int max, int value )
{
GuiWidget *widget = gui_widget_create(
parent, GUI_PROGRESSBAR, x, y, width, height,
default_event_handler, user_event_handler );
/* create surface, wallpaper and frame it */
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height );
SDL_SetColorKey( widget->surface, 0,0 );
stk_surface_apply_wallpaper( widget->surface, 0,0,-1,-1,
gui_theme->widget_wallpaper, -1 );
widget->border = stk_surface_apply_frame(
widget->surface, 0, 0, -1, -1,
gui_theme->widget_frame );
/* size w/o border */
widget->width -= 2 * widget->border;
widget->height -= 2 * widget->border;
/* set value */
widget->spec.progressbar.max = max;
gui_progressbar_set_value( widget, value );
/* done */
return widget;
}
/*
====================================================================
Get/Set value and limit of progressbar.
====================================================================
*/
void gui_progressbar_set_value(
GuiWidget *widget, int value )
{
if ( widget->type != GUI_PROGRESSBAR ) return;
/* set value */
widget->spec.progressbar.value = value;
gui_progressbar_adjust( widget );
/* done */
if ( widget->visible )
gui_widget_draw( widget );
}
void gui_progressbar_set_max(
GuiWidget *widget, int max )
{
if ( widget->type != GUI_PROGRESSBAR ) return;
/* set max */
widget->spec.progressbar.max = max;
gui_progressbar_adjust( widget );
/* done */
if ( widget->visible )
gui_widget_draw( widget );
}
int gui_progressbar_get_value(
GuiWidget *widget, int *value )
{
if ( widget->type != GUI_PROGRESSBAR ) return 0;
*value = widget->spec.progressbar.value;
return 1;
}
int gui_progressbar_get_max(
GuiWidget *widget, int *max )
{
if ( widget->type != GUI_PROGRESSBAR ) return 0;
*max = widget->spec.progressbar.max;
return 1;
}

View File

@@ -0,0 +1,46 @@
/***************************************************************************
gui_progressbar.h - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_PROGRESSBAR_H
#define __GUI_PROGRESSBAR_H
/*
====================================================================
Create a framed progress bar.
====================================================================
*/
GuiWidget *gui_progressbar_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int max, int value );
/*
====================================================================
Get/Set value and limit of progressbar.
====================================================================
*/
void gui_progressbar_set_value(
GuiWidget *progressbar, int value );
void gui_progressbar_set_max(
GuiWidget *progressbar, int max );
int gui_progressbar_get_value(
GuiWidget *progressbar, int *value );
int gui_progressbar_get_max(
GuiWidget *widget, int *max );
#endif

View File

@@ -0,0 +1,244 @@
/***************************************************************************
gui_radiogroup.c - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "gui_widget.h"
#include "gui_radiogroup.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Default event handler
====================================================================
*/
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
int px, py, i;
switch ( event->type ) {
case GUI_DESTROY:
if ( widget->spec.radiogroup.checks )
free( widget->spec.radiogroup.checks );
break;
case GUI_DRAW:
/* display surface */
stk_surface_blit(
widget->surface, 0, 0, -1, -1,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
/* add checkers */
px = widget->screen_region.x +
widget->spec.radiogroup.x;
py = widget->screen_region.y +
widget->spec.radiogroup.y;
for ( i = 0; i < widget->spec.radiogroup.size;
i++, py += widget->spec.radiogroup.offset ) {
if ( widget->spec.radiogroup.checks[i] )
stk_surface_blit(
gui_theme->checkbox,
gui_theme->checkbox_size, 0,
gui_theme->checkbox_size,
gui_theme->checkbox_size,
stk_display, px, py );
}
break;
case GUI_CLICKED:
gui_radiogroup_toggle( widget,
(event->button.y - widget->screen_region.y -
widget->border) / widget->spec.radiogroup.offset );
break;
}
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create a radiogroup or a checkbox which is nothing but a
single entried radiogroup.
'caption': checkbox caption
'items': items - the widget does not modify the pointers
'checked': is True if checkbox checked else False.
Radiogroup selections can be set with gui_radiogroup_select().
====================================================================
*/
GuiWidget* gui_checkbox_create(
GuiWidget *parent, int x, int y, int width, int height, int with_frame,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
char *caption, int checked )
{
GuiWidget *widget;
char *items[1];
items[0] = caption;
/* this is just a single itemed radiogroup */
widget = gui_radiogroup_create(
parent, x, y, width, height, with_frame, user_event_handler,
1, items, 0, 1 );
gui_radiogroup_set_checked( widget, 0, checked );
return widget;
}
GuiWidget* gui_radiogroup_create(
GuiWidget *parent, int x, int y, int width, int height, int with_frame,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int item_count, char **items, int min, int max )
{
int px, py, i, j, gap = 4;
GuiWidget *widget = gui_widget_create(
parent, GUI_RADIOGROUP, x, y, width, height,
default_event_handler, user_event_handler );
/* events */
gui_widget_enable_event( widget, GUI_CLICKED );
/* create surface, wallpaper and frame it */
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height );
SDL_SetColorKey( widget->surface, 0,0 );
stk_surface_apply_wallpaper( widget->surface, 0,0,-1,-1,
gui_theme->widget_wallpaper, -1 );
if ( with_frame )
widget->border = stk_surface_apply_frame(
widget->surface, 0, 0, -1, -1,
gui_theme->widget_frame );
/* size w/o border */
widget->width -= 2 * widget->border;
widget->height -= 2 * widget->border;
/* various */
widget->spec.radiogroup.size = item_count;
widget->spec.radiogroup.min = min;
widget->spec.radiogroup.max = max;
widget->spec.radiogroup.single_check = -1;
/* compute offset of single items */
widget->spec.radiogroup.offset =
(height - 2 * widget->border) /
item_count;
/* position of first checkbox */
widget->spec.radiogroup.x = widget->border + gap;
widget->spec.radiogroup.y = widget->border +
(widget->spec.radiogroup.offset -
gui_theme->checkbox_size) / 2;
/* add empty checkboxes and labels */
gui_theme->label_font->align = STK_FONT_ALIGN_CENTER_Y;
px = widget->spec.radiogroup.x;
py = widget->spec.radiogroup.y;
for ( i = 0, j = 0; i < widget->spec.radiogroup.size;
i++, py += widget->spec.radiogroup.offset, j++ ) {
stk_surface_blit(
gui_theme->checkbox, 0, 0,
gui_theme->checkbox_size,
gui_theme->checkbox_size,
widget->surface, px, py );
stk_font_write( gui_theme->label_font,
widget->surface, px + gui_theme->checkbox_size + gap,
py + gui_theme->checkbox_size/2, -1, items[j] );
}
/* create empty checkers */
widget->spec.radiogroup.checks = calloc( item_count, sizeof( int ) );
if ( widget->spec.radiogroup.checks == 0 )
GUI_ABORT( "Out Of Memory" );
return widget;
}
/*
====================================================================
Set or check if a checkbox in the radiogroup is set.
Stores refresh rects if visible.
====================================================================
*/
void gui_radiogroup_set_checked(
GuiWidget *widget, int id, int check )
{
if ( widget->type != GUI_RADIOGROUP )
return;
if ( id >= widget->spec.radiogroup.size || id < 0 )
return;
/* if there is at maximum one item selectable
we clear the selection to simplify usage */
if ( widget->spec.radiogroup.max == 1 ) {
memset( widget->spec.radiogroup.checks, 0,
widget->spec.radiogroup.size * sizeof( int ) );
widget->spec.radiogroup.check_count = 0;
widget->spec.radiogroup.single_check = -1;
}
if ( check ) {
/* select item if possible */
if ( widget->spec.radiogroup.check_count ==
widget->spec.radiogroup.max )
return;
/* if only one selection is allowed unselect old checker */
widget->spec.radiogroup.checks[id] = 1;
widget->spec.radiogroup.single_check = id;
widget->spec.radiogroup.check_count++;
}
else {
/* unselect item if possible */
if ( widget->spec.radiogroup.check_count ==
widget->spec.radiogroup.min )
return;
if ( widget->spec.radiogroup.checks[id] == 0 )
return;
widget->spec.radiogroup.checks[id] = 0;
widget->spec.radiogroup.single_check = -1;
widget->spec.radiogroup.check_count--;
}
if ( widget->visible )
gui_widget_draw( widget );
}
void gui_radiogroup_toggle( GuiWidget *widget, int id )
{
if ( widget->type != GUI_RADIOGROUP )
return;
if ( id >= widget->spec.radiogroup.size || id < 0 )
return;
gui_radiogroup_set_checked(
widget, id, !widget->spec.radiogroup.checks[id] );
}
int gui_radiogroup_is_checked( GuiWidget *widget, int id )
{
if ( widget->type != GUI_RADIOGROUP )
return 0;
if ( id >= widget->spec.radiogroup.size || id < 0 )
return 0;
return widget->spec.radiogroup.checks[id];
}
/*
====================================================================
For radiogroups with at max one items this returns the currently
checked id or -1.
====================================================================
*/
int gui_radiogroup_get_checked( GuiWidget *widget )
{
if ( widget->type != GUI_RADIOGROUP )
return -1;
if ( widget->spec.radiogroup.max != 1 )
return -1;
return widget->spec.radiogroup.single_check;
}

View File

@@ -0,0 +1,60 @@
/***************************************************************************
gui_radiogroup.h - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_RADIOGROUP_H
#define __GUI_RADIOGROUP_H
/*
====================================================================
Create a radiogroup or a checkbox which is nothing but a
single entried radiogroup.
'caption': checkbox caption
'items': items - the widget does not modify the pointers
'checked': is True if checkbox checked else False.
Radiogroup selections can be set with gui_radiogroup_select().
====================================================================
*/
GuiWidget* gui_checkbox_create(
GuiWidget *parent, int x, int y, int width, int height,
int with_frame,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
char *caption, int checked );
GuiWidget* gui_radiogroup_create(
GuiWidget *parent, int x, int y, int width, int height,
int with_frame,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int item_count, char **items, int min, int max );
/*
====================================================================
Set or check if a checkbox in the radiogroup is set.
Stores refresh rects if visible.
====================================================================
*/
void gui_radiogroup_set_checked(
GuiWidget *radiogroup, int id, int check );
void gui_radiogroup_toggle( GuiWidget *radiogroup, int id );
int gui_radiogroup_is_checked( GuiWidget *radiogroup, int id );
/*
====================================================================
For radiogroups with at max one items this returns the currently
checked id or -1.
====================================================================
*/
int gui_radiogroup_get_checked( GuiWidget *radiogroup );
#endif

View File

@@ -0,0 +1,350 @@
/***************************************************************************
gui_scrollbar.c - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include "gui_widget.h"
#include "gui_button.h"
#include "gui_scrollbar.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Default event handler
====================================================================
*/
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
switch ( event->type ) {
case GUI_DESTROY:
break;
case GUI_DRAW:
/* display surface */
stk_surface_blit(
widget->surface, 0, 0, -1, -1,
stk_display,
widget->screen_region.x,
widget->screen_region.y );
break;
case GUI_BUTTON_PRESSED:
if ( widget->spec.scrollbar.vertical ) {
if ( event->button.y <
widget->spec.scrollbar.track->
screen_region.y )
gui_scrollbar_add( widget,
-widget->spec.scrollbar.jump );
else
gui_scrollbar_add( widget,
widget->spec.scrollbar.jump );
}
else {
if ( event->button.x <
widget->spec.scrollbar.track->
screen_region.x )
gui_scrollbar_add( widget,
-widget->spec.scrollbar.jump );
else
gui_scrollbar_add( widget,
widget->spec.scrollbar.jump );
}
break;
}
}
/*
====================================================================
Warp track button of scrollbar to correct position.
====================================================================
*/
static void gui_scrollbar_update_track( GuiWidget *widget )
{
int offset;
if ( widget->type != GUI_SCROLLBAR ) return;
if ( widget->spec.scrollbar.min == widget->spec.scrollbar.max )
offset = 0;
else
offset =
(((widget->spec.scrollbar.vertical) ?
widget->parent_region.h :
widget->parent_region.w) -
(widget->spec.scrollbar.button_size * 3) ) *
widget->spec.scrollbar.value /
(widget->spec.scrollbar.max - widget->spec.scrollbar.min);
gui_widget_warp( widget->spec.scrollbar.track,
(widget->spec.scrollbar.vertical) ? 0 :
(offset + widget->spec.scrollbar.button_size),
(widget->spec.scrollbar.vertical)?
(offset + widget->spec.scrollbar.button_size) : 0 );
}
/*
====================================================================
Update the scrollbar value by position of track button,
return True if it has changed and call event handler with
GUI_CHANGED.
====================================================================
*/
static int gui_scrollbar_adjust( GuiWidget *widget )
{
int new_value;
if ( widget->type != GUI_SCROLLBAR ) return 0;
new_value = (((widget->spec.scrollbar.vertical) ?
widget->spec.scrollbar.track->parent_region.y :
widget->spec.scrollbar.track->parent_region.x) -
widget->spec.scrollbar.button_size) *
(widget->spec.scrollbar.max - widget->spec.scrollbar.min) /
(((widget->spec.scrollbar.vertical) ?
widget->parent_region.h :
widget->parent_region.w) -
widget->spec.scrollbar.button_size * 3);
if ( new_value != widget->spec.scrollbar.value ) {
widget->spec.scrollbar.value = new_value;
gui_widget_call_user_event_handler(
widget, gui_event_get_simple( GUI_CHANGED ) );
return 1;
}
return 0;
}
/*
====================================================================
Default event handlers for scrollbar buttons: update the
scrollbar if a button was clicked and pass the event to the
scrollbar's user event handler.
====================================================================
*/
static void gui_scrollbar_dec_handler(
GuiWidget *widget, GuiEvent *event )
{
if ( event->type == GUI_CLICKED )
gui_scrollbar_add( widget->parent,
-widget->parent->spec.scrollbar.step );
gui_widget_call_user_event_handler(
widget->parent, event );
}
static void gui_scrollbar_inc_handler(
GuiWidget *widget, GuiEvent *event )
{
if ( event->type == GUI_CLICKED )
gui_scrollbar_add( widget->parent,
widget->parent->spec.scrollbar.step );
gui_widget_call_user_event_handler(
widget->parent, event );
}
static void gui_scrollbar_track_handler(
GuiWidget *widget, GuiEvent *event )
{
int pos;
if ( event->type == GUI_MOTION )
if ( event->motion.button ) {
if ( widget->parent->spec.scrollbar.vertical ) {
/* absolute offset in parent */
pos = widget->parent_region.y +
event->motion.yrel;
if ( pos < widget->parent->spec.scrollbar.button_size )
pos = widget->parent->spec.scrollbar.button_size;
else
if ( pos >= widget->parent->parent_region.h -
(widget->parent->spec.scrollbar.button_size<<1) )
pos = widget->parent->parent_region.h -
(widget->parent->spec.scrollbar.button_size<<1);
/* move */
gui_widget_warp( widget, 0, pos );
}
else {
/* absolute offset in parent */
pos = widget->parent_region.x +
event->motion.xrel;
if ( pos < widget->parent->spec.scrollbar.button_size )
pos = widget->parent->spec.scrollbar.button_size;
else
if ( pos >= widget->parent->parent_region.w -
(widget->parent->spec.scrollbar.button_size<<1) )
pos = widget->parent->parent_region.w -
(widget->parent->spec.scrollbar.button_size<<1);
/* move */
gui_widget_warp( widget, pos, 0 );
}
/* update value */
gui_scrollbar_adjust( widget->parent );
}
/* send event */
gui_widget_call_user_event_handler(
widget->parent, event );
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create an either vertical or horizontal scrollbar. The increase/
decrease/track buttons are square.
====================================================================
*/
GuiWidget* gui_scrollbar_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int vertical, int min, int max, int step, int jump, int value )
{
int size;
GuiWidget *widget = gui_widget_create(
parent, GUI_SCROLLBAR, x, y, width, height,
default_event_handler, user_event_handler );
/* events */
gui_widget_enable_event( widget, GUI_CHANGED );
/* create surface and wallpaper it */
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height );
SDL_SetColorKey( widget->surface, 0,0 );
stk_surface_apply_wallpaper(
widget->surface, 0, 0, -1, -1,
gui_theme->widget_wallpaper, -1 );
/* get scrollbar size and add frame */
if ( vertical ) {
size = width;
stk_surface_apply_frame(
widget->surface, 0, size, size, height - 2 * size,
gui_theme->widget_frame );
}
else {
size = height;
stk_surface_apply_frame(
widget->surface, size, 0, width - 2 * size, size,
gui_theme->widget_frame );
}
/* various */
widget->spec.scrollbar.vertical = vertical;
widget->spec.scrollbar.button_size = size;
/* add inc/dec/track buttons */
widget->spec.scrollbar.dec =
gui_button_create( widget, 0, 0, size, size,
gui_scrollbar_dec_handler,
gui_theme->scrollbar_arrows,
(vertical)?0:
(gui_theme->scrollbar_arrow_size*2),
0,
gui_theme->scrollbar_arrow_size,
gui_theme->scrollbar_arrow_size, 0 );
gui_widget_disable_event( widget->spec.scrollbar.dec, GUI_FOCUS_IN );
gui_widget_disable_event( widget->spec.scrollbar.dec, GUI_FOCUS_OUT );
widget->spec.scrollbar.inc =
gui_button_create( widget,
(vertical)?0:(width-size),
(vertical)?(height-size):0,
size, size,
gui_scrollbar_inc_handler,
gui_theme->scrollbar_arrows,
gui_theme->scrollbar_arrow_size +
((vertical)?0:
(gui_theme->scrollbar_arrow_size*2)),
0,
gui_theme->scrollbar_arrow_size,
gui_theme->scrollbar_arrow_size, 0 );
gui_widget_disable_event( widget->spec.scrollbar.inc, GUI_FOCUS_IN );
gui_widget_disable_event( widget->spec.scrollbar.inc, GUI_FOCUS_OUT );
widget->spec.scrollbar.track =
gui_button_create( widget, 0, 0, size, size,
gui_scrollbar_track_handler,
0,0,0,0,0, 0 );
/* our trackbutton needs the motion event monitored */
gui_widget_enable_event( widget->spec.scrollbar.track, GUI_MOTION );
gui_widget_disable_event( widget->spec.scrollbar.track, GUI_FOCUS_IN );
gui_widget_disable_event( widget->spec.scrollbar.track, GUI_FOCUS_OUT );
/* track grabs focus if pressed to simplify usage */
widget->spec.scrollbar.track->grab_focus = 1;
/* range */
gui_scrollbar_set_range( widget, min, max, step, jump );
gui_scrollbar_set_value( widget, value );
/* done */
return widget;
}
/*
====================================================================
Set or get scrollbar value. Get returns False if this was no
scrollbar.
====================================================================
*/
void gui_scrollbar_set_value( GuiWidget *widget, int value )
{
if ( widget->type == GUI_SCROLLBAR ) {
widget->spec.scrollbar.value = value;
gui_scrollbar_update_track( widget );
}
}
int gui_scrollbar_get_value( GuiWidget *widget, int *value )
{
if ( widget->type != GUI_SCROLLBAR )
return 0;
*value = widget->spec.scrollbar.value;
return 1;
}
/*
====================================================================
Set the range of the scrollbar. Stores refresh rects if visible.
-1 for any value means to keep the current setting.
====================================================================
*/
int gui_scrollbar_set_range(
GuiWidget *widget, int min, int max, int step, int jump )
{
if ( widget->type != GUI_SCROLLBAR )
return 0;
if ( min != -1 ) widget->spec.scrollbar.min = min;
if ( max != -1 ) widget->spec.scrollbar.max = max;
if ( step != -1 ) widget->spec.scrollbar.step = step;
if ( jump != -1 ) widget->spec.scrollbar.jump = jump;
gui_scrollbar_update_track( widget );
return 1;
}
/*
====================================================================
Modify value of scrollbar by the passed amount and update,
return True if it has changed and call event handler with
GUI_CHANGED.
====================================================================
*/
int gui_scrollbar_add( GuiWidget *widget, int change )
{
int old_value = widget->spec.scrollbar.value;
if ( widget->type != GUI_SCROLLBAR ) return 0;
widget->spec.scrollbar.value += change;
if ( widget->spec.scrollbar.value < widget->spec.scrollbar.min )
widget->spec.scrollbar.value = widget->spec.scrollbar.min;
if ( widget->spec.scrollbar.value > widget->spec.scrollbar.max )
widget->spec.scrollbar.value = widget->spec.scrollbar.max;
gui_scrollbar_update_track( widget );
if ( old_value != widget->spec.scrollbar.value ) {
gui_widget_call_user_event_handler(
widget, gui_event_get_simple( GUI_CHANGED ) );
return 1;
}
return 0;
}

View File

@@ -0,0 +1,58 @@
/***************************************************************************
gui_scrollbar.h - description
-------------------
begin : Wed Oct 16 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_SCROLLBAR_H
#define __GUI_SCROLLBAR_H
/*
====================================================================
Create an either vertical or horizontal scrollbar. The increase/
decrease/track buttons are square.
====================================================================
*/
GuiWidget* gui_scrollbar_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int vertical, int min, int max, int step, int jump, int value );
/*
====================================================================
Set or get scrollbar value. Get returns False if this was no
scrollbar.
====================================================================
*/
void gui_scrollbar_set_value( GuiWidget *scrollbar, int value );
int gui_scrollbar_get_value( GuiWidget *scrollbar, int *value );
/*
====================================================================
Set the range of the scrollbar. Stores refresh rects if visible.
-1 for any value means to keep the current setting.
====================================================================
*/
int gui_scrollbar_set_range(
GuiWidget *scrollbar, int min, int max, int step, int jump );
/*
====================================================================
Modify value of scrollbar by the passed amount and update,
return True if it has changed and call event handler with
GUI_CHANGED.
====================================================================
*/
int gui_scrollbar_add( GuiWidget *widget, int change );
#endif

View File

@@ -0,0 +1,256 @@
/***************************************************************************
gui_spinbutton.c - description
-------------------
begin : Sat Oct 19 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "gui_widget.h"
#include "gui_spinbutton.h"
#include "gui_button.h"
#include "gui_edit.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Default event handler
====================================================================
*/
static void default_event_handler(
GuiWidget *widget, GuiEvent *event )
{
switch ( event->type ) {
case GUI_DESTROY:
break;
case GUI_DRAW:
break;
}
}
/*
====================================================================
Handle edit and restrict input to digits and minus. Check range.
The GUI_CHANGED event from the edit is blocked if an invalid
character was added.
====================================================================
*/
static void gui_spinbutton_edit_handler(
GuiWidget *widget, GuiEvent *event )
{
char aux[GUI_SPINBUTTON_LENGTH + 1];
int old_value;
if ( event->type == GUI_CHANGED ) {
old_value = widget->parent->spec.spinbutton.value;
gui_edit_get_text( widget, aux,
GUI_SPINBUTTON_LENGTH + 1, 0, -1 );
widget->parent->spec.spinbutton.value = atoi( aux );
/* check if we hit upper limit */
if ( widget->parent->spec.spinbutton.value >
widget->parent->spec.spinbutton.max ) {
widget->parent->spec.spinbutton.value =
widget->parent->spec.spinbutton.max;
snprintf( aux, GUI_SPINBUTTON_LENGTH + 1,
"%i", widget->parent->spec.spinbutton.value );
gui_edit_set_text( widget, aux );
}
if ( old_value != widget->parent->spec.spinbutton.value )
gui_widget_call_user_event_handler(
widget->parent, event );
}
else
gui_widget_call_user_event_handler(
widget->parent, event );
}
/*
====================================================================
Handle increase/decrease buttons.
====================================================================
*/
static void gui_spinbutton_inc_handler(
GuiWidget *widget, GuiEvent *event )
{
if ( event->type == GUI_CLICKED )
if ( widget->parent->spec.spinbutton.value <
widget->parent->spec.spinbutton.max ) {
widget->parent->spec.spinbutton.value +=
widget->parent->spec.spinbutton.step;
if ( widget->parent->spec.spinbutton.value >
widget->parent->spec.spinbutton.max )
widget->parent->spec.spinbutton.value =
widget->parent->spec.spinbutton.max;
gui_spinbutton_set_value( widget->parent,
widget->parent->spec.spinbutton.value );
gui_widget_call_user_event_handler(
widget->parent,
gui_event_get_simple( GUI_CHANGED ) );
}
gui_widget_call_user_event_handler( widget->parent, event );
}
static void gui_spinbutton_dec_handler(
GuiWidget *widget, GuiEvent *event )
{
if ( event->type == GUI_CLICKED )
if ( widget->parent->spec.spinbutton.value >
widget->parent->spec.spinbutton.min ) {
widget->parent->spec.spinbutton.value -=
widget->parent->spec.spinbutton.step;
if ( widget->parent->spec.spinbutton.value <
widget->parent->spec.spinbutton.min )
widget->parent->spec.spinbutton.value =
widget->parent->spec.spinbutton.min;
gui_spinbutton_set_value( widget->parent,
widget->parent->spec.spinbutton.value );
gui_widget_call_user_event_handler(
widget->parent,
gui_event_get_simple( GUI_CHANGED ) );
}
gui_widget_call_user_event_handler( widget->parent, event );
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
Create a spinbutton which is an alphanumerical edit with an
increase and a decrease button both the size of height x height/2
at the right end of the edit.
====================================================================
*/
GuiWidget* gui_spinbutton_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int min, int max, int step, int value )
{
GuiWidget *widget = gui_widget_create(
parent, GUI_SPINBUTTON, x, y, width, height,
default_event_handler, user_event_handler );
/* events */
gui_widget_enable_event( widget, GUI_CHANGED );
/* build empty surface */
widget->surface = stk_surface_create(
SDL_SWSURFACE, width, height );
/* set range */
widget->spec.spinbutton.min = min;
widget->spec.spinbutton.max = max;
widget->spec.spinbutton.step = step;
/* build edit */
widget->spec.spinbutton.edit = gui_edit_create(
widget, 0, 0, width - height, height,
gui_spinbutton_edit_handler, 2, 0,
GUI_SPINBUTTON_LENGTH, "undefined" );
gui_edit_set_filter(
widget->spec.spinbutton.edit, GUI_EDIT_NUMERICAL );
gui_widget_disable_event(
widget->spec.spinbutton.edit, GUI_FOCUS_IN );
gui_widget_disable_event(
widget->spec.spinbutton.edit, GUI_FOCUS_OUT );
/* by default edit can't be edited */
widget->spec.spinbutton.edit->active = 0;
/* build buttons */
widget->spec.spinbutton.inc = gui_button_create(
widget, width - height, 0, height, height / 2,
gui_spinbutton_inc_handler,
gui_theme->spinbutton_arrows, 0,0,
gui_theme->spinbutton_arrow_size,
gui_theme->spinbutton_arrow_size, 0 );
gui_widget_disable_event(
widget->spec.spinbutton.inc, GUI_FOCUS_IN );
gui_widget_disable_event(
widget->spec.spinbutton.inc, GUI_FOCUS_OUT );
widget->spec.spinbutton.dec = gui_button_create(
widget, width - height, height/2, height, height / 2,
gui_spinbutton_dec_handler,
gui_theme->spinbutton_arrows,
gui_theme->spinbutton_arrow_size,0,
gui_theme->spinbutton_arrow_size,
gui_theme->spinbutton_arrow_size, 0 );
gui_widget_disable_event(
widget->spec.spinbutton.dec, GUI_FOCUS_IN );
gui_widget_disable_event(
widget->spec.spinbutton.dec, GUI_FOCUS_OUT );
/* set value */
gui_spinbutton_set_value( widget, value );
/* done */
return widget;
}
/*
====================================================================
Get/set spinbutton's value. Get returns False if this was no
spinbutton.
====================================================================
*/
void gui_spinbutton_set_value( GuiWidget *widget, int value )
{
char aux[GUI_SPINBUTTON_LENGTH + 1];
if ( widget->type == GUI_SPINBUTTON ) {
widget->spec.spinbutton.value = value;
snprintf( aux, GUI_SPINBUTTON_LENGTH + 1, "%i", value );
gui_edit_set_text( widget->spec.spinbutton.edit, aux );
}
}
int gui_spinbutton_get_value( GuiWidget *widget, int *value )
{
if ( widget->type != GUI_SPINBUTTON )
return 0;
*value = widget->spec.spinbutton.value;
if ( *value < widget->spec.spinbutton.min )
*value = widget->spec.spinbutton.min;
if ( *value > widget->spec.spinbutton.max )
*value = widget->spec.spinbutton.max;
return 1;
}
/*
====================================================================
Set the range of the spinbutton. Stores refresh rects if visible.
-1 for any value means to keep the current setting.
====================================================================
*/
int gui_spinbutton_set_range(
GuiWidget *widget, int min, int max, int step )
{
if ( widget->type != GUI_SPINBUTTON )
return 0;
if ( min != -1 ) widget->spec.spinbutton.min = min;
if ( max != -1 ) widget->spec.spinbutton.max = max;
if ( step != -1 ) widget->spec.spinbutton.step = step;
return 1;
}
/*
====================================================================
(De)Activate edit of spinbutton. If the entered value is greater
than the maximum it is set to maximum. If it's less than minimum
it is _not_ reset (else it would be impossible to enter new
values) However, if the value is queried by
gui_spinbutton_get_value() it is checked for its range.
====================================================================
*/
void gui_spinbutton_enable_edit( GuiWidget *widget, int enable )
{
widget->spec.spinbutton.edit->active = enable;
}

View File

@@ -0,0 +1,65 @@
/***************************************************************************
gui_spinbutton.h - description
-------------------
begin : Sat Oct 19 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_SPINBUTTON_H
#define __GUI_SPINBUTTON_H
/* maximum number of characters (minus/digits) in the edit */
enum { GUI_SPINBUTTON_LENGTH = 15 };
/*
====================================================================
Create a spinbutton which is an alphanumerical edit with an
increase and a decrease button both the size of height x height/2
at the right end of the edit.
====================================================================
*/
GuiWidget* gui_spinbutton_create(
GuiWidget *parent, int x, int y, int width, int height,
void (*user_event_handler)(GuiWidget*,GuiEvent*),
int min, int max, int step, int value );
/*
====================================================================
Get/set spinbutton's value. Get returns False if this was no
spinbutton.
====================================================================
*/
void gui_spinbutton_set_value( GuiWidget *spinbutton, int value );
int gui_spinbutton_get_value( GuiWidget *spinbutton, int *value );
/*
====================================================================
Set the range of the spinbutton. Stores refresh rects if visible.
-1 for any value means to keep the current setting.
====================================================================
*/
int gui_spinbutton_set_range(
GuiWidget *spinbutton, int min, int max, int step );
/*
====================================================================
(De)Activate edit of spinbutton. If the entered value is greater
than the maximum it is set to maximum. If it's less than minimum
it is _not_ reset (else it would be impossible to enter new
values) However, if the value is queried by
gui_spinbutton_get_value() it is checked for its range.
====================================================================
*/
void gui_spinbutton_enable_edit( GuiWidget *spinbutton, int enable );
#endif

View File

@@ -0,0 +1,149 @@
/***************************************************************************
gui_theme.c - description
-------------------
begin : Fri Oct 11 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "gui_theme.h"
#define ABORT( msg ) { fprintf( stderr, "%s\n", msg ); exit(1); }
GuiTheme *gui_theme = 0;
/*
====================================================================
Load a theme from a theme directory. The surface path set by
stk_surface_set_path() is prepended.
====================================================================
*/
GuiTheme* gui_theme_load( char *name )
{
GuiTheme *theme = calloc( 1, sizeof( GuiTheme ) );
if ( theme == 0 ) ABORT( "Out Of Memory" )
theme->box_wallpaper =
stk_surface_load( SDL_SWSURFACE,
"%s/box_wallpaper.png", name );
theme->widget_wallpaper =
stk_surface_load( SDL_SWSURFACE,
"%s/widget_wallpaper.png", name );
theme->box_frame =
stk_surface_load( SDL_SWSURFACE,
"%s/box_frame.png", name );
theme->widget_frame =
stk_surface_load( SDL_SWSURFACE,
"%s/widget_frame.png", name );
theme->button_frame_normal =
stk_surface_load( SDL_SWSURFACE,
"%s/button_frame_normal.png", name );
theme->button_frame_clicked =
stk_surface_load( SDL_SWSURFACE,
"%s/button_frame_clicked.png", name );
theme->button_wallpaper_normal =
stk_surface_load( SDL_SWSURFACE,
"%s/button_wallpaper_normal.png", name );
theme->button_wallpaper_focused =
stk_surface_load( SDL_SWSURFACE,
"%s/button_wallpaper_focused.png", name );
theme->scrollbar_arrows =
stk_surface_load( SDL_SWSURFACE,
"%s/scrollbar_arrows.png", name );
theme->scrollbar_arrow_size =
theme->scrollbar_arrows->h;
theme->checkbox =
stk_surface_load( SDL_SWSURFACE,
"%s/checkbox.png", name );
theme->checkbox_size = theme->checkbox->h;
theme->progress_high =
stk_surface_load( SDL_SWSURFACE,
"%s/progress_high.png", name );
theme->progress_medium =
stk_surface_load( SDL_SWSURFACE,
"%s/progress_medium.png", name );
theme->progress_low =
stk_surface_load( SDL_SWSURFACE,
"%s/progress_low.png", name );
theme->list_item_color =
stk_surface_load( SDL_SWSURFACE,
"%s/list_item_color.png", name );
theme->spinbutton_arrows =
stk_surface_load( SDL_SWSURFACE,
"%s/spinbutton_arrows.png", name );
theme->spinbutton_arrow_size =
theme->spinbutton_arrows->h;
theme->font =
stk_font_load( SDL_SWSURFACE, "%s/font.png", name );
theme->edit_font =
stk_font_load( SDL_SWSURFACE, "%s/font.png", name );
theme->label_font =
stk_font_load( SDL_SWSURFACE, "%s/font.png", name );
theme->button_font = theme->font;
theme->progressbar_font = theme->font;
theme->click_sound =
stk_sound_load( -1, "%s/click.wav", name );
theme->type_sound =
stk_sound_load( -1, "%s/edit.wav", name );
return theme;
}
/*
====================================================================
Free the memory of a surface if not NULL and reset the pointer
to NULL.
====================================================================
*/
void gui_theme_delete( GuiTheme **theme )
{
if ( *theme ) {
stk_surface_free( &(*theme)->box_wallpaper );
stk_surface_free( &(*theme)->widget_wallpaper );
stk_surface_free( &(*theme)->box_frame );
stk_surface_free( &(*theme)->widget_frame );
stk_surface_free( &(*theme)->button_frame_normal );
stk_surface_free( &(*theme)->button_frame_clicked );
stk_surface_free( &(*theme)->button_wallpaper_normal );
stk_surface_free( &(*theme)->button_wallpaper_focused );
stk_surface_free( &(*theme)->scrollbar_arrows );
stk_surface_free( &(*theme)->checkbox );
stk_surface_free( &(*theme)->progress_high );
stk_surface_free( &(*theme)->progress_medium );
stk_surface_free( &(*theme)->progress_low );
stk_surface_free( &(*theme)->list_item_color );
stk_surface_free( &(*theme)->spinbutton_arrows );
stk_font_free( &(*theme)->font );
stk_font_free( &(*theme)->edit_font );
stk_font_free( &(*theme)->label_font );
stk_sound_free( &(*theme)->click_sound );
stk_sound_free( &(*theme)->type_sound );
free( *theme ); *theme = 0;
}
}
/*
====================================================================
Select the current theme. New widgets will use its graphics.
====================================================================
*/
void gui_theme_select( GuiTheme *theme )
{
gui_theme = theme;
}

View File

@@ -0,0 +1,86 @@
/***************************************************************************
gui_theme.h - description
-------------------
begin : Fri Oct 11 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_THEME_H
#define __GUI_THEME_H
#include "stk.h"
/*
====================================================================
All widgets need a basic set of graphics and this is it.
It provides a wallpaper, a frame, a basic button, arrows for
scrollbars etc. However it cannot be changed on runtime so
once a widget is completed it looks like it looks.
====================================================================
*/
typedef struct {
SDL_Surface *box_wallpaper; /* wallpaper for box widget */
SDL_Surface *widget_wallpaper; /* wallpaper for other widgets */
SDL_Surface *box_frame; /* frame for box window */
SDL_Surface *widget_frame; /* frame for other widgets */
SDL_Surface *button_frame_normal,
*button_frame_clicked; /* frames for the different
button types */
SDL_Surface *button_wallpaper_normal,
*button_wallpaper_focused; /* button wallpapers */
StkFont *font; /* standard font */
SDL_Surface *scrollbar_arrows; /* scrollbar arrows */
int scrollbar_arrow_size; /* arrows are square */
SDL_Surface *checkbox; /* checkbox and checker */
int checkbox_size; /* checkboxes are square */
SDL_Surface *progress_high,
*progress_medium,
*progress_low; /* three wallpapers for
progressbar (25%,60%,100%) */
SDL_Surface *list_item_color; /* color of the selection box */
SDL_Surface *spinbutton_arrows; /* scrollbar arrows */
int spinbutton_arrow_size; /* arrows are square */
StkFont *button_font; /* font for button captions */
StkFont *label_font; /* font for labels */
StkFont *progressbar_font;
StkFont *edit_font;
/* sounds */
StkSound *click_sound;
StkSound *type_sound;
} GuiTheme;
/*
====================================================================
Load a theme from a theme directory. The surface path set by
stk_surface_set_path() is prepended.
====================================================================
*/
GuiTheme* gui_theme_load( char *name );
/*
====================================================================
Free the memory of a surface if not NULL and reset the pointer
to NULL.
====================================================================
*/
void gui_theme_delete( GuiTheme **theme );
/*
====================================================================
Select the current theme. New widgets will use its graphics.
====================================================================
*/
void gui_theme_select( GuiTheme *theme );
#endif

View File

@@ -0,0 +1,618 @@
/***************************************************************************
gui_widget.c - description
-------------------
begin : Fri Oct 11 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include <string.h>
#include "gui_widget.h"
extern GuiTheme *gui_theme;
extern SDL_Surface *stk_display;
extern List *gui_root_stack;
extern List *gui_visible_stack;
extern List *gui_timed_stack;
GuiWidget *gui_key_widget = 0;
/* is the last child widget of _all_ visible key grabbing
widgets that was clicked on */
GuiWidget *gui_clicked_widget = 0;
/* is the last child widget of _all_ visible widgets
that was clicked on (used to clear 'pressed' flag) */
GuiWidget *gui_focused_widget = 0;
/* the very toplevel widget of all visible widgets
the mouse pointer hovers above */
/*
====================================================================
LOCALS
====================================================================
*/
/*
====================================================================
Free the memory of a widget and all its subwidgets.
====================================================================
*/
static void gui_widget_delete_intern( GuiWidget *widget )
{
GuiWidget *child;
if ( widget ) {
/* go recursive */
list_reset( widget->widgets );
while ( ( child = list_next( widget->widgets ) ) )
gui_widget_delete_intern( child );
/* free common data */
list_delete( widget->widgets );
stk_surface_free( &widget->surface );
/* free special data */
widget->default_event_handler(
widget, gui_event_get_simple( GUI_DESTROY ) );
/* widget itself */
free( widget );
}
}
/*
====================================================================
Draw the widget and its children. gui_widget_draw() disabled
the display monitoring and will add the widgets screen_region
as update rectangle.
====================================================================
*/
static void gui_widget_draw_intern( GuiWidget *widget )
{
GuiWidget *child = 0;
/* draw widget */
widget->default_event_handler(
widget, gui_event_get_simple( GUI_DRAW ) );
/* draw children */
list_reset( widget->widgets );
while ( ( child = list_next( widget->widgets ) ) )
gui_widget_draw_intern( child );
}
/*
====================================================================
Set visible flag to 'visible' for widget and all children
recursively.
====================================================================
*/
static void gui_widget_show_intern( GuiWidget *widget, int visible )
{
GuiWidget *child;
widget->visible = visible;
list_reset( widget->widgets );
while ( ( child = list_next( widget->widgets ) ) )
gui_widget_show_intern( child, visible );
}
/*
====================================================================
If there are any root windows above this widget in the stack that
overlap this one they need to be redrawn. We clip to the widgets
screen region and redraw all root widgets above.
====================================================================
*/
static void gui_widget_redraw_overlapping_roots(
GuiWidget *widget )
{
ListEntry *entry;
if ( gui_visible_stack->count > 1 )
if ( list_last( gui_visible_stack ) != widget->root ) {
/* clip */
stk_surface_clip( stk_display,
widget->screen_region.x, widget->screen_region.y,
widget->screen_region.w, widget->screen_region.h );
/* get first root widget above */
entry = list_entry(
gui_visible_stack, widget->root );
if ( !entry ) {
fprintf( stderr,
"'visible_stack' corrupted: root widget not found\n" );
return;
}
entry = entry->next;
/* redraw */
while ( entry != gui_visible_stack->tail ) {
gui_widget_draw_intern( (GuiWidget*)entry->item );
entry = entry->next;
}
/* unclip */
stk_surface_clip( stk_display, 0,0,-1,-1 );
}
}
/*
====================================================================
Move position by relative value for all widgets.
====================================================================
*/
static void gui_widget_move_intern(
GuiWidget *widget, int rel_x, int rel_y)
{
GuiWidget *child;
widget->screen_region.x += rel_x;
widget->screen_region.y += rel_y;
widget->parent_region.x += rel_x;
widget->parent_region.y += rel_y;
list_reset( widget->widgets );
while ( ( child = list_next( widget->widgets ) ) )
gui_widget_move_intern( child, rel_x, rel_y );
}
/*
====================================================================
PUBLICS
====================================================================
*/
/*
====================================================================
GUI events
====================================================================
*/
/*
====================================================================
Return pointer to simple event (one that doesn't need
additional data)
====================================================================
*/
static GuiEvent aux_event;
GuiEvent *gui_event_get_simple( int type )
{
aux_event.type = type;
return &aux_event;
}
/*
====================================================================
Initiate a GUI event from an SDL event.
====================================================================
*/
void gui_event_init( GuiEvent *gui_event, SDL_Event *sdl_event )
{
int i;
memset( gui_event, 0, sizeof( GuiEvent ) );
switch ( sdl_event->type ) {
case SDL_MOUSEMOTION:
gui_event->type = GUI_MOTION;
gui_event->motion.x = sdl_event->motion.x;
gui_event->motion.y = sdl_event->motion.y;
gui_event->motion.xrel = sdl_event->motion.xrel;
gui_event->motion.yrel = sdl_event->motion.yrel;
gui_event->motion.state = sdl_event->motion.state;
for ( i = 1; i <= 3; i++ )
if ( sdl_event->motion.state & SDL_BUTTON(i) ) {
gui_event->motion.button = i;
break;
}
break;
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
if ( sdl_event->type == SDL_MOUSEBUTTONUP )
gui_event->type = GUI_BUTTON_RELEASED;
else
gui_event->type = GUI_BUTTON_PRESSED;
gui_event->button.x = sdl_event->button.x;
gui_event->button.y = sdl_event->button.y;
gui_event->button.button = sdl_event->button.button;
break;
case SDL_KEYUP:
case SDL_KEYDOWN:
if ( sdl_event->type == SDL_KEYUP )
gui_event->type = GUI_KEY_RELEASED;
else
gui_event->type = GUI_KEY_PRESSED;
gui_event->key.keysym = sdl_event->key.keysym.sym;
gui_event->key.unicode = sdl_event->key.keysym.unicode;
break;
}
}
/*
====================================================================
GUI widget
====================================================================
*/
/*
====================================================================
Create a basic widget and setup things all different widget types
have in common. If a parent is specified this widget is added to
it's 'widgets' list. Per default following events are enabled:
GUI_ACTIVATED, GUI_DEACTIVATED, GUI_DRAW, GUI_DESTROY,
GUI_FOCUS_IN, GUI_FOCUS_OUT. 'x' or 'y' -1 means to center the
widget.
====================================================================
*/
GuiWidget* gui_widget_create(
GuiWidget *parent, int type,
int x, int y, int width, int height,
void (*default_event_handler)(GuiWidget*,GuiEvent*),
void (*user_event_handler)(GuiWidget*,GuiEvent*) )
{
GuiWidget *widget = calloc( 1, sizeof( GuiWidget ) );
if ( widget == 0 )
GUI_ABORT( "Out Of Memory" )
/* create empty children list */
if ( ( widget->widgets =
list_create( LIST_NO_AUTO_DELETE,
LIST_NO_CALLBACK ) ) == 0 )
GUI_ABORT( "Out Of Memory" )
/* various assignments */
if ( parent ) {
widget->parent = parent;
list_add( widget->parent->widgets, widget );
}
widget->type = type;
widget->root = (parent==0)?widget:parent->root;
widget->active = 1;
widget->default_event_handler = default_event_handler;
widget->user_event_handler = user_event_handler;
/* adjust x,y */
if ( x == -1 ) {
if ( parent )
x = ( parent->width - width ) / 2;
else
x = ( stk_display->w - width ) / 2;
}
if ( y == -1 ) {
if ( parent )
y = ( parent->height - height ) / 2;
else
y = ( stk_display->h - height ) / 2;
}
/* region in parent */
if ( parent == 0 ) {
widget->parent_region.x = x;
widget->parent_region.y = y;
}
else {
widget->parent_region.x = x + widget->parent->border;
widget->parent_region.y = y + widget->parent->border;
}
widget->parent_region.w = width;
widget->parent_region.h = height;
/* screen region */
if ( widget->parent == 0 )
widget->screen_region = widget->parent_region;
else {
widget->screen_region.x =
widget->parent_region.x + parent->screen_region.x;
widget->screen_region.y =
widget->parent_region.y + parent->screen_region.y;
widget->screen_region.w = widget->parent_region.w;
widget->screen_region.h = widget->parent_region.h;
}
/* children size */
widget->width = width; widget->height = height;
/* events */
gui_widget_enable_event( widget, GUI_ACTIVATED );
gui_widget_enable_event( widget, GUI_DEACTIVATED );
gui_widget_enable_event( widget, GUI_DRAW );
gui_widget_enable_event( widget, GUI_DESTROY );
gui_widget_enable_event( widget, GUI_FOCUS_IN );
gui_widget_enable_event( widget, GUI_FOCUS_OUT );
/* if this is a root widget add it to root_stack */
if ( widget->root == widget )
list_add( gui_root_stack, widget );
/* done */
return widget;
}
/*
====================================================================
This function will delete a root widget including all subwidgets.
Subwidgets can't be directly deleted. Resets the widget
pointer to NULL.
====================================================================
*/
void gui_widget_delete( GuiWidget **widget )
{
if ( *widget == 0 ) return;
if ( (*widget)->root != *widget ) {
fprintf( stderr, "You can only delete root widgets!\n" );
return;
}
if ( (*widget)->visible )
list_delete_item( gui_visible_stack, *widget );
if ( (*widget)->event_mask & GUI_TIME_PASSED )
list_delete_item( gui_timed_stack, *widget );
list_delete_item( gui_root_stack, *widget );
gui_widget_delete_intern( *widget );
*widget = 0;
}
/*
====================================================================
If button is deactivated no input events (key,button,motion)
are handled.
====================================================================
*/
void gui_widget_set_active( GuiWidget *widget, int active )
{
int type;
if ( widget->active == active ) return;
widget->active = active;
type = (active)?GUI_ACTIVATED:GUI_DEACTIVATED;
widget->default_event_handler(
widget, gui_event_get_simple( type ) );
gui_widget_call_user_event_handler(
widget, gui_event_get_simple( type ) );
}
/*
====================================================================
Draw the widget and its children if visible.
====================================================================
*/
void gui_widget_draw( GuiWidget *widget )
{
/* update only if visible */
if ( !widget->visible ) return;
/* recursively draw widget */
gui_widget_draw_intern( widget );
/* redraw higher level roots that overlap this widget. */
gui_widget_redraw_overlapping_roots( widget );
/* store update rect */
stk_display_store_rect( &widget->screen_region );
}
/*
====================================================================
Set 'visible' flag and draw widget (store update rects)
if either parent is visible or it has no parent.
(thus is a root window). If it is a root window add it to the
root window stack. This new window will handle incoming events
first.
====================================================================
*/
void gui_widget_show( GuiWidget *widget )
{
if ( widget->visible ) return;
if ( widget->root == widget ) {
list_add( gui_visible_stack, widget );
if ( widget->event_mask & GUI_TIME_PASSED )
list_add( gui_timed_stack, widget );
#ifdef GUI_DEBUG
printf( "show root widget: %i,%i,%i,%i\n",
widget->screen_region.x, widget->screen_region.y,
widget->screen_region.w, widget->screen_region.h );
#endif
/* if this root widget grabs the input the old
gui_key_widget/gui_clicked_widget is obsolete */
if ( widget->grab_input ) {
if ( gui_key_widget ) {
gui_key_widget->default_event_handler(
gui_key_widget,
gui_event_get_simple( GUI_FOCUS_OUT ) );
gui_key_widget = 0;
}
gui_clicked_widget = 0;
}
/* maybe there is a default key grab widget? */
if ( widget->default_key_widget )
gui_key_widget = widget->default_key_widget;
}
gui_widget_show_intern( widget, 1 );
if ( widget->parent == 0 || widget->parent->visible )
gui_widget_draw( widget );
}
/*
====================================================================
Clear 'visible' flag and restore widget if parent is visible.
If there is no parent (thus is a root window) remove it from
stack and redraw the underlying window (which regains control). If
a root widget is hidden the background cannot be restored
as it is unknown.
====================================================================
*/
void gui_widget_hide( GuiWidget *widget )
{
ListEntry *entry;
if ( !widget->visible ) return;
gui_widget_show_intern( widget, 0 );
if ( widget->root == widget ) {
entry = list_entry( gui_visible_stack, widget );
if ( entry ) {
/* remove */
entry = entry->next;
list_delete_entry(
gui_visible_stack, entry->prev );
/* FIX ME! redraw all open roots */
entry = gui_visible_stack->head->next;
while ( entry != gui_visible_stack->tail ) {
gui_widget_draw( (GuiWidget*)entry->item );
entry = entry->next;
}
}
if ( widget->event_mask & GUI_TIME_PASSED )
list_delete_item( gui_timed_stack, widget );
}
else {
/* draw parent's background */
stk_surface_blit( widget->parent->surface,
widget->parent_region.x, widget->parent_region.y,
widget->parent_region.w, widget->parent_region.h,
stk_display,
widget->screen_region.x, widget->screen_region.y );
/* redraw higher level roots that overlap this widget. */
gui_widget_redraw_overlapping_roots( widget );
/* store update rect */
stk_display_store_rect( &widget->screen_region );
}
/* check if gui_key_widget is still valid */
if ( gui_key_widget )
if ( widget == gui_key_widget ||
widget == gui_key_widget->parent ||
widget == gui_key_widget->root )
gui_key_widget = 0;
}
/*
====================================================================
Modify the event mask of a widget to define which events will
be passed to user_event_handler.
====================================================================
*/
void gui_widget_enable_event( GuiWidget *widget, int event )
{
widget->event_mask |= (1L << event);
}
void gui_widget_disable_event( GuiWidget *widget, int event )
{
widget->event_mask &= ~(1L << event);
}
/*
====================================================================
Pass GuiEvent to user defined callback if it has been installed
and the event mask flag is True for this event.
====================================================================
*/
void gui_widget_call_user_event_handler(
GuiWidget *widget, GuiEvent *event )
{
if ( widget->user_event_handler )
if ( widget->event_mask & (1L << event->type) )
widget->user_event_handler( widget, event );
}
/*
====================================================================
Handle the GUI event by calling the default_event_handler()
and the user_event_handler() if one has been installed.
====================================================================
*/
void gui_widget_handle_event( GuiWidget *widget, GuiEvent *event )
{
widget->default_event_handler( widget, event );
gui_widget_call_user_event_handler( widget, event );
}
/*
====================================================================
Move widget within parent window by a relative value. If the
widget is visible the changes will be drawn to screen.
====================================================================
*/
void gui_widget_move( GuiWidget *widget, int rel_x, int rel_y )
{
if ( !widget->visible )
gui_widget_move_intern( widget, rel_x, rel_y );
else {
gui_widget_hide( widget );
gui_widget_move_intern( widget, rel_x, rel_y );
gui_widget_show( widget );
}
}
/*
====================================================================
Move widget within parent window by an absolute value. If the
widget is visible the changes will be drawn to screen.
====================================================================
*/
void gui_widget_warp( GuiWidget *widget, int abs_x, int abs_y )
{
if ( widget->parent )
gui_widget_move( widget,
abs_x - widget->parent_region.x +
widget->parent->border,
abs_y - widget->parent_region.y +
widget->parent->border );
else
gui_widget_move( widget,
abs_x - widget->parent_region.x,
abs_y - widget->parent_region.y );
}
/*
====================================================================
Apply parents background or wallpaper within the frame (if
any) of the widget's surface keeping the frame.
====================================================================
*/
void gui_widget_apply_wallpaper(
GuiWidget *widget, SDL_Surface *wallpaper, int alpha )
{
if ( widget->parent )
stk_surface_blit( widget->parent->surface,
widget->parent_region.x +
widget->border,
widget->parent_region.y +
widget->border,
widget->parent_region.w -
(widget->border<<1),
widget->parent_region.h -
(widget->border<<1),
widget->surface,
widget->border, widget->border );
else
stk_surface_apply_wallpaper(
widget->surface, widget->border, widget->border,
widget->parent_region.w - (widget->border<<1),
widget->parent_region.h - (widget->border<<1),
wallpaper, alpha );
}
/*
====================================================================
Browse the widget tree and set 'focused' true for all widgets
that have the mouse pointer above them. 'focused_widget'
returns the deepest widget that is focused.
====================================================================
*/
void gui_widget_update_focus(
GuiWidget *widget, int mx, int my, GuiWidget **focused_widget )
{
GuiWidget *child;
if ( !widget->active )
return;
if ( !STK_IN_RECT( widget->screen_region, mx, my ) )
return;
widget->focused = 1;
*focused_widget = widget;
/* handle children recursively */
list_reset( widget->widgets );
while ( ( child = list_next( widget->widgets ) ) )
gui_widget_update_focus( child, mx, my, focused_widget );
}
/*
====================================================================
Get direct access to widget's surface.
====================================================================
*/
SDL_Surface *gui_widget_get_surface( GuiWidget *widget )
{
return widget->surface;
}
/*
====================================================================
That key grabbing child of a root widget.
====================================================================
*/
void gui_widget_set_default_key_widget(
GuiWidget *root, GuiWidget *key_widget )
{
if ( root->root != root ) return;
root->default_key_widget = key_widget;
}

View File

@@ -0,0 +1,386 @@
/***************************************************************************
gui_widget.h - description
-------------------
begin : Fri Oct 11 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __GUI_WIDGET_H
#define __GUI_WIDGET_H
#include "list.h"
#include "stk.h"
#include "gui_theme.h"
//#define GUI_DEBUG
#define GUI_ABORT( msg ) \
{ fprintf( stderr, "Fatal GUI Error!\n%s\n", msg ); exit( 1 ); }
/*
====================================================================
GUI events
====================================================================
*/
/* types */
enum {
GUI_NONE = 0,
GUI_DESTROY, /* widget is deleted */
GUI_ACTIVATED,
GUI_DEACTIVATED, /* handle _input_ events or not */
GUI_DRAW, /* draw widget to stk_display */
GUI_TIME_PASSED, /* msecs since last TIME_PASSED event */
GUI_FOCUS_IN, /* widget lost focus */
GUI_FOCUS_OUT, /* widget gained focus */
GUI_MOTION, /* motion within widget */
GUI_BUTTON_PRESSED,
GUI_BUTTON_RELEASED, /* mouse button */
GUI_KEY_PRESSED,
GUI_KEY_RELEASED, /* key */
GUI_CLICKED, /* mouse button pressed + released */
GUI_CHANGED, /* type-dependent data changed */
GUI_ITEM_SELECTED,
GUI_ITEM_UNSELECTED /* list item (un)selected */
};
/* event */
typedef union {
int type;
struct {
int type;
int x, y, button;
} button;
struct {
int type;
int x, y, xrel, yrel;
int button; /* first button pressed */
int state; /* full button mask */
} motion;
struct {
int type;
int keysym;
int unicode;
} key;
struct {
int type;
int x, y;
} item;
struct {
int type;
int ms;
} time;
} GuiEvent;
/*
====================================================================
Return pointer to simple event (one that doesn't need
additional data)
====================================================================
*/
GuiEvent *gui_event_get_simple( int type );
/*
====================================================================
Initiate a GUI event from an SDL event.
====================================================================
*/
void gui_event_init( GuiEvent *gui_event, SDL_Event *sdl_event );
/*
====================================================================
GUI widget
====================================================================
*/
/* types */
enum {
GUI_BOX = 0,
GUI_BUTTON,
GUI_LABEL,
GUI_ICON,
GUI_PROGRESSBAR,
GUI_RADIOGROUP,
GUI_SCROLLBAR,
GUI_EDIT,
GUI_LIST,
GUI_SPINBUTTON
};
/* GUI widget -
for simplicity only one is used for all types */
typedef struct _GuiWidget {
struct _GuiWidget *parent; /* widget's parent */
struct _GuiWidget *root; /* widget's root (top parent) */
List *widgets; /* widget's children */
struct _GuiWidget *focused_widget; /* recursivly in widgets */
struct _GuiWidget *default_key_widget;
/* child 'default_key_widget' will grab key input if this
is a root widget that is shown */
int type; /* button, label, icon ... */
int visible; /* gui_widget_draw() updates screen */
int active; /* accept events */
int focused; /* mouse pointer somewhere in widget */
int grab_input; /* deny event handling to lower roots */
int grab_keys; /* grab key input if clicked */
int grab_focus; /* grab focus IF PRESSED thus motion events
are directly passed to widgets handler.
the focus is not updated until mouse button
is released again. */
int pressed; /* memorize 'button_pressed' event */
SDL_Rect screen_region; /* absolute region in screen (clipped) */
SDL_Rect parent_region; /* relative region in parent */
/* CALLBACKS */
void (*default_event_handler)(struct _GuiWidget*,GuiEvent*);
/* handles event and updates a widget (graphics etc) */
void (*user_event_handler)(struct _GuiWidget*,GuiEvent*);
/* user's possibility to react on event. is NOT called
from the default_event_handler but from
gui_widget_handle_event() itself. */
/* USED BY ALL WIDGETS BUT TYPE DEPENDANT */
int border; /* size of frame around widget */
int width, height; /* widget's size w/o border */
int event_mask; /* events passed to user's event_handler */
SDL_Surface *surface; /* picture of widget */
/* SPECS */
union {
/* LABEL */
struct {
StkFont *font;
int align; /* alignment of text */
char *text; /* text */
} label;
/* PROGRESSBAR */
struct {
int max; /* maximum value */
int value; /* current value */
int length; /* current length */
SDL_Surface *wallpaper; /* current beam wallpaper */
} progressbar;
/* RADIOGROUP */
struct {
int min; /* minimum selections required */
int max; /* minimum selections allowed */
int size; /* number of items */
int *checks; /* 'checked' flag for each item */
int check_count; /* number of selections */
int single_check; /* id of last item selected */
int x, y; /* position of first checkbox in parent */
int offset; /* offset from one item to next */
} radiogroup;
/* SCROLLBAR */
struct {
int vertical; /* vertical scrollbar? */
int button_size; /* size of (square) buttons */
int value; /* current value */
int min, max; /* range of value */
int step; /* offset for up/down */
int jump; /* offset for pgup/pgdown */
struct _GuiWidget *inc;
struct _GuiWidget *dec; /* pointers to 'widgets' */
struct _GuiWidget *track; /* special widget that is NOT
in the 'widgets' list */
} scrollbar;
/* EDIT */
struct {
int filter[SDLK_LAST]; /* characters accepted */
int multi_line; /* single-line edit or text area? */
int size; /* character limit */
char *buffer; /* string of edit */
char *display_buffer; /* contains 'height' lines of
length 'width' separated by \0 which will be
displayed when drawing. is rendered by
gui_edit_adjust_cursor() */
int length; /* current string length */
int width; /* characters per line */
int height; /* number of lines */
int x, y; /* position in visible characters */
int y_offset; /* used to center single-line edits */
int pos; /* position of edit cursor */
int start; /* first character displayed */
int line; /* first line displayed (start/width) */
} edit;
/* LIST */
struct {
int columns; /* (fixed) number of columns */
int item_width;
int item_height; /* item size */
int gap; /* space between items */
int rows_per_page; /* number of rows displayed */
int item_count; /* number of items */
int rows; /* number of rows */
int select_type; /* no, single, multi select */
int *checks; /* NO_SELECT: unused
SINGLE_SELECT: id of selected item
MULTI_SELECT: flags for all items
whether they are
selected or not */
SDL_Surface
*render_buffer; /* 'render_item' renders item
into this surface*/
int (*render_item)(int,int,SDL_Surface*); /* user
defined render callback to render item x,y into
surface. This item is only displayed
if 'render_item' returns True. */
struct _GuiWidget *scrollbar; /* pointer to
'widgets' */
} list;
/* SPINBUTTON */
struct {
int min, max, step; /* range of value */
int value; /* value */
struct _GuiWidget *edit; /* pointer to edit */
struct _GuiWidget *inc;
struct _GuiWidget *dec; /* pointer to buttons */
} spinbutton;
} spec;
} GuiWidget;
/*
====================================================================
Create a basic widget and setup things all different widget types
have in common. If a parent is specified this widget is added to
it's 'widgets' list. 'x' or 'y' -1 means to center the
widget.
====================================================================
*/
GuiWidget* gui_widget_create(
GuiWidget *parent, int type,
int x, int y, int width, int height,
void (*default_event_handler)(GuiWidget*,GuiEvent*),
void (*user_event_handler)(GuiWidget*,GuiEvent*) );
/*
====================================================================
This function will delete a root widget including all subwidgets.
Subwidgets can't be directly deleted. Resets the widget
pointer to NULL.
====================================================================
*/
void gui_widget_delete( GuiWidget **widget );
/*
====================================================================
If button is deactivated no input events (key,button,motion)
are handled.
====================================================================
*/
void gui_widget_set_active( GuiWidget *widget, int active );
/*
====================================================================
Draw the widget and its children if visible.
====================================================================
*/
void gui_widget_draw( GuiWidget *widget );
/*
====================================================================
Set 'visible' flag and draw widget (store update rects)
if either parent is visible or it has no parent.
(thus is a root window). If it is a root window add it to the
root window stack. This new window will handle incoming events
first.
====================================================================
*/
void gui_widget_show( GuiWidget *widget );
/*
====================================================================
Clear 'visible' flag and restore widget if parent is visible.
If there is no parent (thus is a root window) remove it from
stack and redraw the underlying window (which regains control). If
a root widget is hidden the background cannot be restored
as it is unknown.
====================================================================
*/
void gui_widget_hide( GuiWidget *widget );
/*
====================================================================
Modify the event mask of a widget to define which events will
be passed to user_event_handler. Update timed_stack if
GUI_TIME_PASSED is enabled/disabled.
====================================================================
*/
void gui_widget_enable_event( GuiWidget *widget, int event );
void gui_widget_disable_event( GuiWidget *widget, int event );
/*
====================================================================
Pass GuiEvent to user defined callback if it has been installed
and the event mask flag is True for this event.
====================================================================
*/
void gui_widget_call_user_event_handler(
GuiWidget *widget, GuiEvent *event );
/*
====================================================================
Handle the GUI event by calling the default_event_handler()
and the user_event_handler() if one has been installed.
====================================================================
*/
void gui_widget_handle_event( GuiWidget *widget, GuiEvent *event );
/*
====================================================================
Move widget within parent window by a relative value. If the
widget is visible the changes will be drawn to screen.
====================================================================
*/
void gui_widget_move( GuiWidget *widget, int rel_x, int rel_y );
/*
====================================================================
Move widget within parent window by an absolute value. If the
widget is visible the changes will be drawn to screen.
====================================================================
*/
void gui_widget_warp( GuiWidget *widget, int abs_x, int abs_y );
/*
====================================================================
Apply parents background or wallpaper within the frame (if
any) of the widget's surface.
====================================================================
*/
void gui_widget_apply_wallpaper(
GuiWidget *widget, SDL_Surface *wallpaper, int alpha );
/*
====================================================================
Browse the widget tree and set 'focused' true for all widgets
that have the mouse pointer above them. 'focused_widget'
returns the deepest widget that is focused.
====================================================================
*/
void gui_widget_update_focus(
GuiWidget *widget, int mx, int my, GuiWidget **focused_widget );
/*
====================================================================
Get direct access to widget's surface.
====================================================================
*/
SDL_Surface *gui_widget_get_surface( GuiWidget *widget );
/*
====================================================================
That key grabbing child of a root widget.
====================================================================
*/
void gui_widget_set_default_key_widget(
GuiWidget *root, GuiWidget *key_widget );
#endif

View File

@@ -0,0 +1,360 @@
/***************************************************************************
list.c - description
-------------------
begin : Sun Sep 2 2001
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdlib.h>
#include "list.h"
/*
====================================================================
Create a new list
auto_delete: Free memory of data pointer when deleting entry
callback: Use this callback to free memory of data including
the data pointer itself.
Return Value: List pointer
====================================================================
*/
List *list_create( int auto_delete, void (*callback)(void*) )
{
List *list = calloc( 1, sizeof( List ) );
list->head = calloc( 1, sizeof( ListEntry ) );
list->tail = calloc( 1, sizeof( ListEntry ) );
list->head->next = list->tail;
list->head->prev = list->head;
list->tail->next = list->tail;
list->tail->prev = list->head;
list->auto_delete = auto_delete;
list->callback = callback;
list->cur_entry = list->head;
return list;
}
/*
====================================================================
Delete list and entries.
====================================================================
*/
void list_delete( List *list )
{
list_clear( list );
free( list->head );
free( list->tail );
free( list );
}
/*
====================================================================
Delete all entries but keep the list. Reset current_entry to head
pointer.
====================================================================
*/
void list_clear( List *list )
{
while( !list_empty( list ) ) list_delete_pos( list, 0 );
}
/*
====================================================================
Insert new item at position.
Return Value: True if successful else False.
====================================================================
*/
int list_insert( List *list, void *item, int pos )
{
int i;
ListEntry *cur = list->head;
ListEntry *new_entry = 0;
/* check if insertion possible */
if ( pos < 0 || pos > list->count ) return 0;
if ( item == 0 ) return 0;
/* get to previous entry */
for (i = 0; i < pos; i++) cur = cur->next;
/* create and anchor new entry */
new_entry = calloc( 1, sizeof( ListEntry ) );
new_entry->item = item;
new_entry->next = cur->next;
new_entry->prev = cur;
cur->next->prev = new_entry;
cur->next = new_entry;
list->count++;
return 1;
}
/*
====================================================================
Add new item at the end of the list.
====================================================================
*/
int list_add( List *list, void *item )
{
ListEntry *new_entry = 0;
/* check if insertion possible */
if ( item == 0 ) return 0;
/* create and anchor new entry */
new_entry = calloc( 1, sizeof( ListEntry ) );
new_entry->item = item;
new_entry->next = list->tail;
new_entry->prev = list->tail->prev;
list->tail->prev->next = new_entry;
list->tail->prev = new_entry;
list->count++;
return 1;
}
/*
====================================================================
Delete item at position. If this was the current entry update
current_entry to valid previous pointer.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_pos( List *list, int pos )
{
int i;
ListEntry *cur = list->head;
/* check if deletion possbile */
if ( list_empty( list ) ) return 0;
if ( pos < 0 || pos >= list->count ) return 0;
/* get to correct entry */
for ( i = 0; i <= pos; i++ ) cur = cur->next;
/* modify anchors */
cur->next->prev = cur->prev;
cur->prev->next = cur->next;
/* decrease counter */
list->count--;
/* check current_entry */
if ( list->cur_entry == cur )
list->cur_entry = list->cur_entry->prev;
/* free memory */
if ( list->auto_delete ) {
if ( list->callback )
(list->callback)( cur->item );
else
free( cur->item );
}
free( cur );
return 1;
}
/*
====================================================================
Delete item if in list. If this was the current entry update
current_entry to valid previous pointer.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_item( List *list, void *item )
{
return list_delete_pos( list, list_check( list, item ) );
}
/*
====================================================================
Delete entry.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_entry( List *list, ListEntry *entry )
{
/* delete possible? */
if ( entry == 0 ) return 0;
if ( list->count == 0 ) return 0;
if ( entry == list->head || entry == list->tail ) return 0;
/* adjust anchor and counter */
entry->prev->next = entry->next;
entry->next->prev = entry->prev;
list->count--;
/* check current_entry */
if ( list->cur_entry == entry )
list->cur_entry = list->cur_entry->prev;
/* free memory */
if ( list->auto_delete ) {
if ( list->callback )
(list->callback)( entry->item );
else
free( entry->item );
}
free( entry );
return 1;
}
/*
====================================================================
Get item from position if in list.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_get( List *list, int pos )
{
int i;
ListEntry *cur = list->head;
if ( pos < 0 || pos >= list->count ) return 0;
for ( i = 0; i <= pos; i++ ) cur = cur->next;
return cur->item;
}
/*
====================================================================
Check if item's in list.
Return Value: Position of item else -1.
====================================================================
*/
int list_check( List *list, void *item )
{
int pos = -1;
ListEntry *cur = list->head->next;
while ( cur != list->tail ) {
pos++;
if ( cur->item == item ) break;
cur = cur->next;
}
if ( cur == list->tail ) pos = -1; /* item not found */
return pos;
}
/*
====================================================================
Return first item stored in list and set current_entry to this
entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_first( List *list )
{
list->cur_entry = list->head->next;
return list->head->next->item;
}
/*
====================================================================
Return last item stored in list and set current_entry to this
entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_last( List *list )
{
list->cur_entry = list->tail->prev;
return list->tail->prev->item;
}
/*
====================================================================
Return item in current_entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_current( List *list )
{
return list->cur_entry->item;
}
/*
====================================================================
Reset current_entry to head of list.
====================================================================
*/
void list_reset( List *list )
{
list->cur_entry = list->head;
}
/*
====================================================================
Get next item and update current_entry (reset if tail reached)
Return Value: Item pointer if found else Null (if tail of list).
====================================================================
*/
void* list_next( List *list )
{
list->cur_entry = list->cur_entry->next;
if ( list->cur_entry == list->tail ) list_reset( list );
return list->cur_entry->item;
}
/*
====================================================================
Get previous item and update current_entry.
Return Value: Item pointer if found else Null (if head of list).
====================================================================
*/
void* list_prev( List *list )
{
list->cur_entry = list->cur_entry->prev;
return list->cur_entry->item;
}
/*
====================================================================
Delete the current entry if not tail or head. This is the entry
that contains the last returned item by list_next/prev().
Return Value: True if it was a valid deleteable entry.
====================================================================
*/
int list_delete_current( List *list )
{
if ( list->cur_entry == 0 || list->cur_entry == list->head || list->cur_entry == list->tail ) return 0;
list_delete_entry( list, list->cur_entry );
return 1;
}
/*
====================================================================
Check if list is empty.
Return Value: True if list counter is 0 else False.
====================================================================
*/
int list_empty( List *list )
{
return list->count == 0;
}
/*
====================================================================
Return entry containing the passed item.
Return Value: True if entry found else False.
====================================================================
*/
ListEntry *list_entry( List *list, void *item )
{
ListEntry *entry = list->head->next;
while ( entry != list->tail ) {
if ( entry->item == item ) return entry;
entry = entry->next;
}
return 0;
}
/*
====================================================================
Transfer an entry from one list to another list by removing from
'source' and adding to 'dest' thus if source does not contain
the item this is equvalent to list_add( dest, item ).
====================================================================
*/
void list_transfer( List *source, List *dest, void *item )
{
int old_auto_flag;
/* add to destination */
list_add( dest, item );
/* as the pointer is added to dest without changes only the empty
entry must be deleted in source */
old_auto_flag = source->auto_delete;
source->auto_delete = LIST_NO_AUTO_DELETE;
list_delete_item( source, item );
source->auto_delete = old_auto_flag;
}
/*
====================================================================
Deqeue the first list entry. (must not use auto_delete therefore)
====================================================================
*/
void *list_dequeue( List *list )
{
void *item;
if ( list->count > 0 ) {
item = list->head->next->item;
list_delete_pos( list, 0 );
return item;
}
else
return 0;
}

View File

@@ -0,0 +1,202 @@
/***************************************************************************
list.h - description
-------------------
begin : Sun Sep 2 2001
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __LIST_H
#define __LIST_H
#ifdef __cplusplus
extern "C" {
#endif
/*
====================================================================
Dynamic list handling data as void pointers.
====================================================================
*/
typedef struct _ListEntry {
struct _ListEntry *next;
struct _ListEntry *prev;
void *item;
} ListEntry;
typedef struct {
int auto_delete;
int count;
ListEntry *head;
ListEntry *tail;
void (*callback)(void*);
ListEntry *cur_entry;
} List;
/*
====================================================================
Create a new list
auto_delete: Free memory of data pointer when deleting entry
callback: Use this callback to free memory of data including
the data pointer itself.
Return Value: List pointer
====================================================================
*/
enum { LIST_NO_AUTO_DELETE = 0, LIST_AUTO_DELETE };
enum { LIST_NO_CALLBACK = 0 };
List *list_create( int auto_delete, void (*callback)(void*) );
/*
====================================================================
Delete list and entries.
====================================================================
*/
void list_delete( List *list );
/*
====================================================================
Delete all entries but keep the list. Reset current_entry to head
pointer.
====================================================================
*/
void list_clear( List *list );
/*
====================================================================
Insert new item at position.
Return Value: True if successful else False.
====================================================================
*/
int list_insert( List *list, void *item, int pos );
/*
====================================================================
Add new item at the end of the list.
====================================================================
*/
int list_add( List *list, void *item );
/*
====================================================================
Delete item at pos. If this was the current entry update
current_entry to valid previous pointer.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_pos( List *list, int pos );
/*
====================================================================
Delete item if in list. If this was the current entry update
current_entry to valid previous pointer.
Return Value: True if successful else False.
====================================================================
*/
int list_delete_item( List *list, void *item );
/*
====================================================================
Delete entry.
====================================================================
*/
int list_delete_entry( List *list, ListEntry *entry );
/*
====================================================================
Get item from position if in list.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_get( List *list, int pos );
/*
====================================================================
Check if item's in list.
Return Value: Position of item else -1.
====================================================================
*/
int list_check( List *list, void *item );
/*
====================================================================
Return first item stored in list and set current_entry to this
entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_first( List *list );
/*
====================================================================
Return last item stored in list and set current_entry to this
entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_last( List *list );
/*
====================================================================
Return item in current_entry.
Return Value: Item pointer if found else Null pointer.
====================================================================
*/
void* list_current( List *list );
/*
====================================================================
Reset current_entry to head of list.
====================================================================
*/
void list_reset( List *list );
/*
====================================================================
Get next item and update current_entry (reset if tail reached).
Return Value: Item pointer if found else Null (if tail of list).
====================================================================
*/
void* list_next( List *list );
/*
====================================================================
Get previous item and update current_entry.
Return Value: Item pointer if found else Null (if head of list).
====================================================================
*/
void* list_prev( List *list );
/*
====================================================================
Delete the current entry if not tail or head. This is the entry
that contains the last returned item by list_next/prev().
Return Value: True if it was a valid deleteable entry.
====================================================================
*/
int list_delete_current( List *list );
/*
====================================================================
Check if list is empty.
Return Value: True if list counter is 0 else False.
====================================================================
*/
int list_empty( List *list );
/*
====================================================================
Return entry containing the passed item.
Return Value: True if entry found else False.
====================================================================
*/
ListEntry *list_entry( List *list, void *item );
/*
====================================================================
Transfer an entry from one list to another list by removing from
'source' and adding to 'dest' thus if source does not contain
the item this is equvalent to list_add( dest, item ).
====================================================================
*/
void list_transfer( List *source, List *dest, void *item );
/*
====================================================================
Deqeue the first list entry. (must not use auto_delete therefore)
====================================================================
*/
void *list_dequeue( List *list );
#ifdef __cplusplus
};
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,502 @@
/***************************************************************************
stk.h - description
-------------------
begin : Thu Oct 12 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef __STK_H
#define __STK_H
#include <SDL.h>
#ifdef AUDIO_ENABLED
#include <SDL_mixer.h>
#endif
/* GENERAL */
#define SDL_NONFATAL 0x10000000
#define STK_ABORT( msg ) \
{ fprintf( stderr, "Fatal STK Error!\n%s\n", msg ); exit( 1 ); }
#define STK_IN_RECT( rect, mx, my ) \
( mx >= (rect).x && my >= (rect).y && \
mx < (rect).x + (rect).w && my < (rect).y + (rect).h )
#define STK_OPAQUE SDL_ALPHA_OPAQUE
#define STK_TRANSPARENT SDL_ALPHA_TRANSPARENT
enum {
STK_BUTTON_LEFT = 1,
STK_BUTTON_MIDDLE,
STK_BUTTON_RIGHT,
STK_WHEEL_UP,
STK_WHEEL_DOWN,
STK_BUTTON_COUNT
};
/*
====================================================================
Initiate SDL, build a default cursor and install the clean
up function stk_quit().
====================================================================
*/
void stk_init( int flags );
/*
====================================================================
Block until either a key or button was pressed. If SDL_QUIT
was received this will set stk_quit_request True.
====================================================================
*/
void stk_wait_for_input( void );
/* SCREEN */
/*
====================================================================
Open a display with the passed settings. Depth may be modified due
to Xserver settings and if the resolution is completely
unavailable 640 x 480 x 16 x SDL_SWSURFACE is opened.
If the display is already open it is closed and re-opened.
There is no function to close the display as this is handled by the
stk_quit() function installed by stk_init().
The display can be accessed by
extern SDL_Surface *stk_display;
This funtion returns True if the wanted width and height are
available, False if not and it aborts when no display is found.
====================================================================
*/
int stk_display_open( int flags, int width, int height, int depth );
/*
====================================================================
Add an update rectangle that will be updated by
stk_display_update(). Regardless of clipping the rectangles
must fit the screen else it'll raise an X error.
If NULL is passed as 'rect' the whole screen is stored for update.
====================================================================
*/
void stk_display_store_rect( SDL_Rect *rect );
/*
====================================================================
Store the destination rectangle of the last blit operation. SDL
modified this rectangle to the actually updated clipping region.
====================================================================
*/
void stk_display_store_drect( void );
/*
====================================================================
Either update all gathered rects or simply the full screen.
In any case the stored regions are cleared.
====================================================================
*/
enum {
STK_UPDATE_ALL = 0,
STK_UPDATE_RECTS
};
void stk_display_update( int type );
/*
====================================================================
Fade the current contents of the display either in or out. 'time'
is the time in milliseconds the fading is supposed to take.
====================================================================
*/
enum {
STK_FADE_IN = 0,
STK_FADE_OUT,
STK_FADE_DEFAULT_TIME = 350
};
void stk_display_fade( int type, int time );
/*
====================================================================
Take a screenshot and save it to screenshot[index].bmp in the
current directory.
====================================================================
*/
void stk_display_take_screenshot();
/*
====================================================================
Switch fullscreen/windowed for current resolution.
====================================================================
*/
void stk_display_apply_fullscreen( int fullscreen );
/* SURFACE */
/*
====================================================================
If stk_surface_load() is called with a relative path this prefix
is added. Default is '.'; 'path' is copied.
====================================================================
*/
void stk_surface_set_path( char *path );
/*
====================================================================
Load a surface from a path. If it's not an absolute directory
(starting with '/') the prefix passed in stk_surface_set_path()
is prepended.
If a video mode was set the surface will be converted to its
format to speed up blitting. As resource either BMP or PNG may
be provided.
If SDL_NONFATAL is passed a warning is displayed and the function
returns NULL else it will exit the program with an error.
The default color key of the surface is black and no alpha.
====================================================================
*/
SDL_Surface* stk_surface_load( int flags, char *format, ... );
/*
====================================================================
Create a surface with the given size and the format of the
video mode which must be set.
The default color key of the surface is black and no alpha.
====================================================================
*/
SDL_Surface* stk_surface_create( int flags, int width, int height );
/*
====================================================================
Free the memory of a surface if not NULL and reset the pointer
to NULL.
====================================================================
*/
void stk_surface_free( SDL_Surface **surface );
/*
====================================================================
Blit retangle from 'src' to 'dest' with current alpha of 'src'.
If 'sw' is -1 the full source width is used, 'sh' analogue.
stk_display_store_drect() can be used to store the update rect
of the blitted surface.
====================================================================
*/
void stk_surface_blit(
SDL_Surface *src, int sx, int sy, int sw, int sh,
SDL_Surface *dest, int dx, int dy );
/*
====================================================================
Different from stk_surface_blit() this function temporarily
overwrites 'src's alpha value. It is not recommended to use
this function if performance is important as it is 10 times slower
than an SDL_SetAlpha() combined with stk_surface_blit().
====================================================================
*/
void stk_surface_alpha_blit(
SDL_Surface *src, int sx, int sy, int sw, int sh,
SDL_Surface *dest, int dx, int dy, int alpha );
/*
====================================================================
Fill a rectangle of the surface with a given color of the format
0xRRGGBB. 'dw' == -1 and 'dh' == -1 have the same effect as in
stk_surface_blit().
====================================================================
*/
void stk_surface_fill(
SDL_Surface *dest, int dx, int dy, int dw, int dh,
int color );
/*
====================================================================
Set the clipping region of a surface. All blit operations into
this surface will only have effect within the clipping region.
'dw' == -1 and 'dh' == -1 have the same effect as in
stk_surface_blit().
====================================================================
*/
void stk_surface_clip(
SDL_Surface *dest, int dx, int dy, int dw, int dh );
/*
====================================================================
Lock/unlock surface for direct access.
====================================================================
*/
#define stk_surface_lock( surface ) \
if (SDL_MUSTLOCK((surface))) SDL_LockSurface((surface))
#define stk_surface_unlock( surface ) \
if (SDL_MUSTLOCK((surface))) SDL_UnlockSurface((surface))
/*
====================================================================
Get or set a pixel from/to a surface. This time the pixel must
already be in SDL format.
====================================================================
*/
void stk_surface_set_pixel(
SDL_Surface *dest, int dx, int dy, Uint32 pixel );
Uint32 stk_surface_get_pixel( SDL_Surface *src, int sx, int sy );
/*
====================================================================
Convert part of the surface to gray and if 'dark' is set cut the
brightness in half. 'dw' == -1 and 'dh' == -1 have the same
effect as in tk_surface_blit().
====================================================================
*/
void stk_surface_gray(
SDL_Surface *dest, int dx, int dy, int dw, int dh, int dark );
/*
====================================================================
Add a 3D frame to surface and dark to contents. The frame border
is 'border' thick.
====================================================================
*/
void stk_surface_add_3dframe(
SDL_Surface *dest, int dx, int dy, int dw, int dh, int border );
/*
====================================================================
Fill the surface with the wallpaper (clipped)
====================================================================
*/
void stk_surface_apply_wallpaper(
SDL_Surface *dest, int dx, int dy, int dw, int dh,
SDL_Surface *wallpaper, int alpha );
/*
====================================================================
Apply a frame to the surface. The frame resource provides the eight
square-like parts for the frame composed as a little frame: corners
and sides.
'dw' == -1 and 'dh' == -1 have the same effect as in
stk_surface_blit().
Returns the size of the border.
====================================================================
*/
int stk_surface_apply_frame(
SDL_Surface *dest, int dx, int dy, int dw, int dh,
SDL_Surface *frame );
/* FIXED FONT */
enum {
STK_FONT_ALIGN_LEFT = (1L << 1),
STK_FONT_ALIGN_RIGHT = (1L << 2),
STK_FONT_ALIGN_TOP = (1L << 3),
STK_FONT_ALIGN_BOTTOM = (1L << 4),
STK_FONT_ALIGN_CENTER_X = (1L << 5),
STK_FONT_ALIGN_CENTER_Y = (1L << 6)
};
typedef struct {
SDL_Surface *surface;
int align; /* text aligment */
int width; /* of a single character */
int height; /* of a single character */
} StkFont;
/*
====================================================================
Load a fixed font which is simply a surface containing the ASCII
characters from 32 (blank) to 96 (whatever) where all characters
have the same width.
====================================================================
*/
StkFont* stk_font_load( int flags, char *format, ... );
/*
====================================================================
Free a font if not NULL and reset pointer to NULL.
====================================================================
*/
void stk_font_free( StkFont **font );
/*
====================================================================
Write string to surface. If 'alpha' is -1 the font is displayed
with the current alpha value else the new alpha is used and kept.
stk_display_store_drect() can be used to store the update rect
of the written string.
====================================================================
*/
void stk_font_write(
StkFont *font, SDL_Surface *dest, int dx, int dy,
int alpha, char *string );
/*
====================================================================
Query the length of the string in pixels.
====================================================================
*/
#define stk_font_string_width( font, string ) \
(strlen(string) * font->width)
/* CURSOR */
/*
====================================================================
Build an SDL cursor with the given hotspot. The resource mask
contains 'b' for black 'w' for white and ' ' for transparent.
There are two cursors provided:
extern SDL_Cursor *empty_cursor (all transparent)
extern SDL_Cursor *std_cursor (SDL standard cursor)
====================================================================
*/
SDL_Cursor* stk_cursor_create(
int width, int height, int hot_x, int hot_y, char *src );
/*
====================================================================
Free a cursor if not NULL and reset pointer to NULL.
====================================================================
*/
void stk_cursor_free( SDL_Cursor **cursor );
/* TIMER */
/*
====================================================================
Reset the timer.
====================================================================
*/
void stk_timer_reset( void );
/*
====================================================================
Get the time since last call or reset.
====================================================================
*/
int stk_timer_get_time( void );
/* AUDIO */
/*
====================================================================
Open mixer. If this fails an error message is
displayed (program doesn't abort) and all stk_audio and stk_sound
functions have no effect.
'frequency': 11025, 22050, 44100 ...
'format': MIX_DEFAULT_FORMAT is recommended
'channels': mono(1) or stereo(2)
'chunksize': mix buffer size (1024 Bytes recommended)
Passing 0 for an argument means to use the SDL default:
22050Hz in format AUDIO_S16LSB stereo with 1024 bytes chunksize
stk_audio_open() installs stk_audio_close() as exit function.
There are 8 channels available for mixing.
====================================================================
*/
int stk_audio_open(
int frequency, Uint16 format, int channels, int chunksize );
/*
====================================================================
Close mixer if previously opened.
====================================================================
*/
void stk_audio_close( void );
/*
====================================================================
If stk_sound_load() is called with a relative path this prefix
is added. Default is '.'; 'path' is copied.
====================================================================
*/
void stk_audio_set_path( char *path );
/*
====================================================================
Enable/disable sound. If disabled stk_sound_play () has no effect.
====================================================================
*/
void stk_audio_enable_sound( int enable );
/*
====================================================================
Set default volume of all sounds: 0 - 128
====================================================================
*/
void stk_audio_set_sound_volume( int volume );
/*
====================================================================
Fade out a specific sound channel. If 'channel is -1 all
channels fade out. 'ms' is the time the fading shall take.
====================================================================
*/
void stk_audio_fade_out( int channel, int ms );
/* SOUND */
typedef struct {
#ifdef AUDIO_ENABLED
Mix_Chunk *chunk; /* SDL_Mixer's sound buffer */
#endif
int channel;
int volume;
} StkSound;
/*
====================================================================
Load a sound from a path. If it's not an absolute directory
(starting with '/') the prefix passed in stk_sound_set_path()
is prepended. Loading sounds is non-fatal thus if a sound
cannot be found it is created but empty. In this case
a warning is displayed.
The volume is set to the default set by
stk_audio_set_sound_volume(). Sounds with an equal 'channel'
will share it so if a new sound is played the old one breaks up
thus channel should be used to group sounds.
If channel is -1 the first available channel is used
to play sound.
====================================================================
*/
StkSound *stk_sound_load( int channel, char *format, ... );
/*
====================================================================
Free the memory of a sound if not NULL and reset the pointer
to NULL.
====================================================================
*/
void stk_sound_free( StkSound **sound );
/*
====================================================================
Set channel/volume of sound.
====================================================================
*/
void stk_sound_set_volume( StkSound *sound, int volume );
void stk_sound_set_channel( StkSound *sound, int channel );
/*
====================================================================
Play a sound.
====================================================================
*/
void stk_sound_play( StkSound *sound );
/*
====================================================================
Play a sound at horizontal position x..
====================================================================
*/
void stk_sound_play_x( int x, StkSound *sound );
/*
====================================================================
Fade out the channel of this sound.
====================================================================
*/
void stk_sound_fade_out( StkSound *sound, int ms );
#endif