From: Florian Zeitz Date: Fri, 14 Dec 2012 19:08:22 +0000 (+0100) Subject: Initial commit X-Git-Url: https://git.babelmonkeys.de/?a=commitdiff_plain;h=4209f8ee8ad516cab6a88159d0bffde8e3d5a03a;p=jubjub.git Initial commit --- 4209f8ee8ad516cab6a88159d0bffde8e3d5a03a diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3516bb4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*.o +*.so +*.dylib +*~ +.deps +aclocal.m4 +autom4te.cache +buildsys.mk +config.h +config.h.in +config.log +config.status +configure diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..22d6ae5 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +PROG = jubjub$(PROG_SUFFIX) + +SRCS = src/core/main.m \ + src/gui/gtk/JubGtkUI.m + +include buildsys.mk + +CPPFLAGS += -Isrc/core -Isrc/gui/gtk -Isrc/gui/common + +LD = $(OBJC) +LDFLAGS = -Wl,--export-dynamic + +CFLAGS += -Werror -faddress-sanitizer diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..14657bc --- /dev/null +++ b/autogen.sh @@ -0,0 +1,4 @@ +#!/bin/sh +aclocal -I m4 || exit 1 +autoconf || exit 1 +autoheader || exit 1 diff --git a/buildsys.mk.in b/buildsys.mk.in new file mode 100644 index 0000000..0930cd4 --- /dev/null +++ b/buildsys.mk.in @@ -0,0 +1,794 @@ +# +# Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 +# Jonathan Schleifer +# +# https://webkeks.org/git/?p=buildsys.git +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice is present in all copies. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +AS = @AS@ +CC = @CC@ +CXX = @CXX@ +CPP = @CPP@ +DC = @DC@ +ERLC = @ERLC@ +OBJC = @OBJC@ +OBJCXX = @OBJCXX@ +AR = @AR@ +LD = ${CC} +RANLIB = @RANLIB@ +PYTHON = @PYTHON@ +ASFLAGS = @ASFLAGS@ +CFLAGS = @CFLAGS@ +CXXFLAGS = @CXXFLAGS@ +CPPFLAGS = @CPPFLAGS@ +DFLAGS = @DFLAGS@ +ERLCFLAGS = @ERLCFLAGS@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCXXFLAGS = @OBJCXXFLAGS@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_RPATH = @LDFLAGS_RPATH@ +LIBS = @LIBS@ +PYTHON_FLAGS = @PYTHON_FLAGS@ +PROG_IMPLIB_NEEDED = @PROG_IMPLIB_NEEDED@ +PROG_IMPLIB_LDFLAGS = @PROG_IMPLIB_LDFLAGS@ +PROG_SUFFIX = @EXEEXT@ +LIB_CFLAGS = @LIB_CFLAGS@ +LIB_LDFLAGS = @LIB_LDFLAGS@ +LIB_PREFIX = @LIB_PREFIX@ +LIB_SUFFIX = @LIB_SUFFIX@ +PLUGIN_CFLAGS = @PLUGIN_CFLAGS@ +PLUGIN_LDFLAGS = @PLUGIN_LDFLAGS@ +PLUGIN_SUFFIX = @PLUGIN_SUFFIX@ +INSTALL_LIB = @INSTALL_LIB@ +UNINSTALL_LIB = @UNINSTALL_LIB@ +CLEAN_LIB = @CLEAN_LIB@ +AS_DEPENDS = @AS_DEPENDS@ +CC_DEPENDS = @CC_DEPENDS@ +CXX_DEPENDS = @CXX_DEPENDS@ +OBJC_DEPENDS = @OBJC_DEPENDS@ +OBJCXX_DEPENDS = @OBJCXX_DEPENDS@ +LN_S = @LN_S@ +MKDIR_P = mkdir -p +INSTALL = @INSTALL@ +SHELL = @SHELL@ +MSGFMT = @MSGFMT@ +JAVAC = @JAVAC@ +JAVACFLAGS = @JAVACFLAGS@ +JAR = @JAR@ +WINDRES = @WINDRES@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +plugindir ?= ${libdir}/${PACKAGE_NAME} +datarootdir = @datarootdir@ +datadir = @datadir@ +includedir = @includedir@ +includesubdir ?= ${PACKAGE_NAME} +localedir = @localedir@ +localename ?= ${PACKAGE_NAME} +mandir = @mandir@ +mansubdir ?= man1 + +OBJS1 = ${SRCS:.c=.o} +OBJS2 = ${OBJS1:.cc=.o} +OBJS3 = ${OBJS2:.cxx=.o} +OBJS4 = ${OBJS3:.d=.o} +OBJS5 = ${OBJS4:.erl=.beam} +OBJS6 = ${OBJS5:.java=.class} +OBJS7 = ${OBJS6:.m=.o} +OBJS8 = ${OBJS7:.mm=.o} +OBJS9 = ${OBJS8:.py=.pyc} +OBJS10 = ${OBJS9:.rc=.o} +OBJS11 = ${OBJS10:.S=.o} +OBJS += ${OBJS11:.xpm=.o} + +LIB_OBJS = ${OBJS:.o=.lib.o} +PLUGIN_OBJS = ${OBJS:.o=.plugin.o} + +MO_FILES = ${LOCALES:.po=.mo} + +.SILENT: +.SUFFIXES: +.SUFFIXES: .beam .c .c.dep .cc .cc.dep .class .cxx .cxx.dep .d .erl .lib.o .java .mo .m .m.dep .mm .mm.dep .o .plugin.o .po .py .pyc .rc .S .S.dep .xpm +.PHONY: all subdirs pre-depend depend install install-extra uninstall uninstall-extra clean distclean locales ${SUBDIRS} + +all: + ${MAKE} ${MFLAGS} subdirs + ${MAKE} ${MFLAGS} depend + ${MAKE} ${STATIC_LIB} ${STATIC_LIB_NOINST} ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${SHARED_LIB} ${SHARED_LIB_NOINST} ${PLUGIN} ${PLUGIN_NOINST} ${PROG} ${PROG_NOINST} ${JARFILE} locales + +subdirs: ${SUBDIRS} + +${SUBDIRS}: + for i in $@; do \ + ${DIR_ENTER}; \ + ${MAKE} ${MFLAGS} || exit $$?; \ + ${DIR_LEAVE}; \ + done + +depend: pre-depend ${SRCS} + regen=0; \ + deps=""; \ + test -f .deps || regen=1; \ + for i in ${SRCS}; do \ + case $$i in \ + *.c) \ + if test x"${CC_DEPENDS}" = x"yes"; then \ + test $$i -nt .deps && regen=1; \ + deps="$$deps $$i.dep"; \ + fi; \ + ;; \ + *.cc | *.cxx) \ + if test x"${CXX_DEPENDS}" = x"yes"; then \ + test $$i -nt .deps && regen=1; \ + deps="$$deps $$i.dep"; \ + fi; \ + ;; \ + *.m) \ + if test x"${OBJC_DEPENDS}" = x"yes"; then \ + test $$i -nt .deps && regen=1; \ + deps="$$deps $$i.dep"; \ + fi; \ + ;; \ + *.mm) \ + if test x"${OBJCXX_DEPENDS}" = x"yes"; then \ + test $$i -nt .deps && regen=1; \ + deps="$$deps $$i.dep"; \ + fi; \ + ;; \ + *.S) \ + if test x"${AS_DEPENDS}" = x"yes"; then \ + test $$i -nt .deps && regen=1; \ + deps="$$deps $$i.dep"; \ + fi; \ + ;; \ + esac; \ + done; \ + if test x"$$regen" = x"1" -a x"$$deps" != x""; then \ + ${DEPEND_STATUS}; \ + if ${MAKE} ${MFLAGS} $$deps && cat $$deps >.deps; then \ + rm -f $$deps; \ + ${DEPEND_OK}; \ + else \ + :> .deps; \ + touch -t 0001010000 .deps; \ + ${DEPEND_FAILED}; \ + fi; \ + fi + +.c.c.dep: + ${CPP} ${CPPFLAGS} ${CFLAGS} -M $< | \ + sed 's/^\([^\.]*\)\.o:/\1.o \1.lib.o \1.plugin.o:/' >$@ || \ + { rm -f $@; false; } + +.cc.cc.dep .cxx.cxx.dep: + ${CPP} ${CPPFLAGS} ${CXXFLAGS} -M $< | \ + sed 's/^\([^\.]*\)\.o:/\1.o \1.lib.o \1.plugin.o:/' >$@ || \ + { rm -f $@; false; } + +.m.m.dep: + ${CPP} ${CPPFLAGS} ${OBJCFLAGS} -M $< | \ + sed 's/^\([^\.]*\)\.o:/\1.o \1.lib.o \1.plugin.o:/' >$@ || \ + { rm -f $@; false; } + +.mm.mm.dep: + ${CPP} ${CPPFLAGS} ${OBJCPPFLAGS} -M $< | \ + sed 's/^\([^\.]*\)\.o:/\1.o \1.lib.o \1.plugin.o:/' >$@ || \ + { rm -f $@; false; } + +.S.S.dep: + ${CPP} ${CPPFLAGS} ${ASFLAGS} -M $< | \ + sed 's/^\([^\.]*\)\.o:/\1.o \1.lib.o \1.plugin.o:/' >$@ || \ + { rm -f $@; false; } + +pre-depend: + +${PROG} ${PROG_NOINST}: ${EXT_DEPS} ${OBJS} ${OBJS_EXTRA} + ${LINK_STATUS} + if ${LD} -o $@ ${OBJS} ${OBJS_EXTRA} ${LDFLAGS} ${LIBS}; then \ + ${LINK_OK}; \ + else \ + ${LINK_FAILED}; \ + fi + +${JARFILE}: ${EXT_DEPS} ${JAR_MANIFEST} ${OBJS} ${OBJS_EXTRA} + ${LINK_STATUS} + if test x"${JAR_MANIFEST}" != x""; then \ + if ${JAR} cfm ${JARFILE} ${JAR_MANIFEST} ${OBJS} ${OBJS_EXTRA}; then \ + ${LINK_OK}; \ + else \ + ${LINK_FAILED}; \ + fi \ + else \ + if ${JAR} cf ${JARFILE} ${OBJS} ${OBJS_EXTRA}; then \ + ${LINK_OK}; \ + else \ + ${LINK_FAILED}; \ + fi \ + fi + +${SHARED_LIB} ${SHARED_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA} + ${LINK_STATUS}; \ + objs=""; \ + ars=""; \ + for i in ${LIB_OBJS} ${LIB_OBJS_EXTRA}; do \ + case $$i in \ + *.a) \ + ars="$$ars $$i" \ + ;; \ + *.o) \ + objs="$$objs $$i" \ + ;; \ + esac \ + done; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + mkdir -p $$dir; \ + cd $$dir; \ + ${AR} x ../$$i; \ + for j in *.o; do \ + objs="$$objs $$dir/$$j"; \ + done; \ + cd ..; \ + done; \ + if ${LD} -o $@ $$objs ${LIB_LDFLAGS} ${LDFLAGS} ${LIBS}; then \ + ${LINK_OK}; \ + else \ + ${LINK_FAILED}; \ + fi; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + done + +${PLUGIN} ${PLUGIN_NOINST}: ${EXT_DEPS} ${PLUGIN_OBJS} + ${LINK_STATUS} + objs=""; \ + ars=""; \ + for i in ${PLUGIN_OBJS}; do \ + case $$i in \ + *.a) \ + ars="$$ars $$i" \ + ;; \ + *.o) \ + objs="$$objs $$i" \ + ;; \ + esac \ + done; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + mkdir -p $$dir; \ + cd $$dir; \ + ${AR} x ../$$i; \ + for j in *.o; do \ + objs="$$objs $$dir/$$j"; \ + done; \ + cd ..; \ + done; \ + if ${LD} -o $@ $$objs ${PLUGIN_LDFLAGS} ${LDFLAGS} ${LIBS}; then \ + ${LINK_OK}; \ + else \ + ${LINK_FAILED}; \ + fi; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + done + +${STATIC_LIB} ${STATIC_LIB_NOINST}: ${EXT_DEPS} ${OBJS} ${OBJS_EXTRA} + ${LINK_STATUS} + rm -f $@ + objs=""; \ + ars=""; \ + for i in ${OBJS} ${OBJS_EXTRA}; do \ + case $$i in \ + *.a) \ + ars="$$ars $$i" \ + ;; \ + *.o) \ + objs="$$objs $$i" \ + ;; \ + esac \ + done; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + mkdir -p $$dir; \ + cd $$dir; \ + ${AR} x ../$$i; \ + for j in *.o; do \ + objs="$$objs $$dir/$$j"; \ + done; \ + cd ..; \ + done; \ + if ${AR} cr $@ $$objs && ${RANLIB} $@; then \ + ${LINK_OK}; \ + else \ + ${LINK_FAILED}; \ + rm -f $@; \ + fi; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + done + +${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST}: ${EXT_DEPS} ${LIB_OBJS} ${LIB_OBJS_EXTRA} + ${LINK_STATUS} + rm -f $@ + objs=""; \ + ars=""; \ + for i in ${LIB_OBJS} ${LIB_OBJS_EXTRA}; do \ + case $$i in \ + *.a) \ + ars="$$ars $$i" \ + ;; \ + *.o) \ + objs="$$objs $$i" \ + ;; \ + esac \ + done; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + mkdir -p $$dir; \ + cd $$dir; \ + ${AR} x ../$$i; \ + for j in *.o; do \ + objs="$$objs $$dir/$$j"; \ + done; \ + cd ..; \ + done; \ + if ${AR} cr $@ $$objs && ${RANLIB} $@; then \ + ${LINK_OK}; \ + else \ + ${LINK_FAILED}; \ + rm -f $@; \ + fi; \ + for i in $$ars; do \ + dir=".$$(echo $$i | sed 's/\//_/g').objs"; \ + rm -fr $$dir; \ + done + +locales: ${MO_FILES} + +.c.o: + ${COMPILE_STATUS} + if ${CC} ${CFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi +.c.lib.o: + ${COMPILE_LIB_STATUS} + if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_LIB_OK}; \ + else \ + ${COMPILE_LIB_FAILED}; \ + fi +.c.plugin.o: + ${COMPILE_PLUGIN_STATUS} + if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_PLUGIN_OK}; \ + else \ + ${COMPILE_PLUGIN_FAILED}; \ + fi + +.cc.o .cxx.o: + ${COMPILE_STATUS} + if ${CXX} ${CXXFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi +.cc.lib.o .cxx.lib.o: + ${COMPILE_LIB_STATUS} + if ${CXX} ${LIB_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_LIB_OK}; \ + else \ + ${COMPILE_LIB_FAILED}; \ + fi +.cc.plugin.o .cxx.plugin.o: + ${COMPILE_PLUGIN_STATUS} + if ${CXX} ${PLUGIN_CFLAGS} ${CXXFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_PLUGIN_OK}; \ + else \ + ${COMPILE_PLUGIN_FAILED}; \ + fi + +.d.o: + ${COMPILE_STATUS} + if test x"$(basename ${DC})" = x"dmd"; then \ + if ${DC} ${DFLAGS} -c -of$@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi \ + else \ + if ${DC} ${DFLAGS} -c -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi \ + fi + +.erl.beam: + ${COMPILE_STATUS} + if ${ERLC} ${ERLCFLAGS} -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi + +.java.class: + ${COMPILE_STATUS} + if ${JAVAC} ${JAVACFLAGS} $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi + +.m.o: + ${COMPILE_STATUS} + if ${OBJC} ${OBJCFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi +.m.lib.o: + ${COMPILE_LIB_STATUS} + if ${OBJC} ${LIB_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_LIB_OK}; \ + else \ + ${COMPILE_LIB_FAILED}; \ + fi +.m.plugin.o: + ${COMPILE_PLUGIN_STATUS} + if ${OBJC} ${PLUGIN_CFLAGS} ${OBJCFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_PLUGIN_OK}; \ + else \ + ${COMPILE_PLUGIN_FAILED}; \ + fi + +.mm.o: + ${COMPILE_STATUS} + if ${OBJCXX} ${OBJCXXFLAGS} ${OBJCFLAGS} ${CXXFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi +.mm.lib.o: + ${COMPILE_LIB_STATUS} + if ${OBJCXX} ${LIB_CFLAGS} ${OBJCXXFLAGS} ${OBJCFLAGS} ${CXXFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_LIB_OK}; \ + else \ + ${COMPILE_LIB_FAILED}; \ + fi +.mm.plugin.o: + ${COMPILE_PLUGIN_STATUS} + if ${OBJCXX} ${PLUGIN_CFLAGS} ${OBJCXXFLAGS} ${OBJCFLAGS} ${CXXFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_PLUGIN_OK}; \ + else \ + ${COMPILE_PLUGIN_FAILED}; \ + fi + +.po.mo: + ${COMPILE_STATUS} + if ${MSGFMT} -c -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi + +.py.pyc: + ${COMPILE_STATUS} + if ${PYTHON} ${PYTHON_FLAGS} -c "import py_compile; py_compile.compile('$<')"; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi + +.rc.o .rc.lib.o .rc.plugin.o: + ${COMPILE_STATUS} + if ${WINDRES} ${CPPFLAGS} -J rc -O coff -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi + +.S.o: + ${COMPILE_STATUS} + if ${AS} ${ASFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi +.S.lib.o: + ${COMPILE_LIB_STATUS} + if ${AS} ${LIB_CFLAGS} ${ASFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_LIB_OK}; \ + else \ + ${COMPILE_LIB_FAILED}; \ + fi +.S.plugin.o: + ${COMPILE_PLUGIN_STATUS} + if ${AS} ${PLUGIN_CFLAGS} ${ASFLAGS} ${CPPFLAGS} -c -o $@ $<; then \ + ${COMPILE_PLUGIN_OK}; \ + else \ + ${COMPILE_PLUGIN_FAILED}; \ + fi + +.xpm.o: + ${COMPILE_STATUS} + if ${CC} ${CFLAGS} ${CPPFLAGS} -x c -c -o $@ $<; then \ + ${COMPILE_OK}; \ + else \ + ${COMPILE_FAILED}; \ + fi +.xpm.lib.o: + ${COMPILE_LIB_STATUS} + if ${CC} ${LIB_CFLAGS} ${CFLAGS} ${CPPFLAGS} -x c -c -o $@ $<; then \ + ${COMPILE_LIB_OK}; \ + else \ + ${COMPILE_LIB_FAILED}; \ + fi +.xpm.plugin.o: + ${COMPILE_PLUGIN_STATUS} + if ${CC} ${PLUGIN_CFLAGS} ${CFLAGS} ${CPPFLAGS} -x c -c -o $@ $<; then \ + ${COMPILE_PLUGIN_OK}; \ + else \ + ${COMPILE_PLUGIN_FAILED}; \ + fi + +install: all install-extra + for i in ${SUBDIRS}; do \ + ${DIR_ENTER}; \ + ${MAKE} ${MFLAGS} install || exit $$?; \ + ${DIR_LEAVE}; \ + done + + for i in ${SHARED_LIB}; do \ + ${INSTALL_STATUS}; \ + if ${MKDIR_P} ${DESTDIR}${libdir} ${INSTALL_LIB}; then \ + ${INSTALL_OK}; \ + else \ + ${INSTALL_FAILED}; \ + fi \ + done + + for i in ${STATIC_LIB} ${STATIC_PIC_LIB}; do \ + ${INSTALL_STATUS}; \ + if ${MKDIR_P} ${DESTDIR}${libdir} && ${INSTALL} -m 644 $$i ${DESTDIR}${libdir}/$$i; then \ + ${INSTALL_OK}; \ + else \ + ${INSTALL_FAILED}; \ + fi \ + done + + for i in ${PLUGIN}; do \ + ${INSTALL_STATUS}; \ + if ${MKDIR_P} ${DESTDIR}${plugindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${plugindir}/$$i; then \ + ${INSTALL_OK}; \ + else \ + ${INSTALL_FAILED}; \ + fi \ + done + + for i in ${DATA}; do \ + ${INSTALL_STATUS}; \ + if ${MKDIR_P} $$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i) && ${INSTALL} -m 644 $$i ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ + ${INSTALL_OK}; \ + else \ + ${INSTALL_FAILED}; \ + fi \ + done + + for i in ${PROG}; do \ + ${INSTALL_STATUS}; \ + if ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i; then \ + ${INSTALL_OK}; \ + else \ + ${INSTALL_FAILED}; \ + fi \ + done + + for i in ${INCLUDES}; do \ + ${INSTALL_STATUS}; \ + if ${MKDIR_P} ${DESTDIR}${includedir}/${includesubdir} && ${INSTALL} -m 644 $$i ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ + ${INSTALL_OK}; \ + else \ + ${INSTALL_FAILED}; \ + fi \ + done + + for i in ${MO_FILES}; do \ + ${INSTALL_STATUS}; \ + if ${MKDIR_P} ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES && ${INSTALL} -m 644 $$i ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo; then \ + ${INSTALL_OK}; \ + else \ + ${INSTALL_FAILED}; \ + fi \ + done + + for i in ${MAN}; do \ + ${INSTALL_STATUS}; \ + if ${MKDIR_P} ${DESTDIR}${mandir}/${mansubdir} && ${INSTALL} -m 644 $$i ${DESTDIR}${mandir}/${mansubdir}/$$i; then \ + ${INSTALL_OK}; \ + else \ + ${INSTALL_FAILED}; \ + fi \ + done + +install-extra: + +uninstall: uninstall-extra + for i in ${SUBDIRS}; do \ + ${DIR_ENTER}; \ + ${MAKE} ${MFLAGS} uninstall || exit $$?; \ + ${DIR_LEAVE}; \ + done + + for i in ${SHARED_LIB}; do \ + if test -f ${DESTDIR}${libdir}/$$i; then \ + if : ${UNINSTALL_LIB}; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi; \ + done + + for i in ${STATIC_LIB} ${STATIC_PIC_LIB}; do \ + if test -f ${DESTDIR}${libdir}/$$i; then \ + if rm -f ${DESTDIR}${libdir}/$$i; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi \ + done + + for i in ${PLUGIN}; do \ + if test -f ${DESTDIR}${plugindir}/$$i; then \ + if rm -f ${DESTDIR}${plugindir}/$$i; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi \ + done + -rmdir ${DESTDIR}${plugindir} >/dev/null 2>&1 + + for i in ${DATA}; do \ + if test -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ + if rm -f ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi; \ + rmdir "$$(dirname ${DESTDIR}${datadir}/${PACKAGE_NAME}/$$i)" >/dev/null 2>&1 || true; \ + done + -rmdir ${DESTDIR}${datadir}/${PACKAGE_NAME} >/dev/null 2>&1 + + for i in ${PROG}; do \ + if test -f ${DESTDIR}${bindir}/$$i; then \ + if rm -f ${DESTDIR}${bindir}/$$i; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi \ + done + + for i in ${INCLUDES}; do \ + if test -f ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ + if rm -f ${DESTDIR}${includedir}/${includesubdir}/$$i; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi \ + done + -rmdir ${DESTDIR}${includedir}/${includesubdir} >/dev/null 2>&1 + + for i in ${MO_FILES}; do \ + if test -f ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo; then \ + if rm -f ${DESTDIR}${localedir}/$${i%.mo}/LC_MESSAGES/${localename}.mo; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi \ + done + + for i in ${MAN}; do \ + if test -f ${DESTDIR}${mandir}/${mansubdir}/$$i; then \ + if rm -f ${DESTDIR}${mandir}/${mansubdir}/$$i; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi \ + done + +uninstall-extra: + +clean: + for i in ${SUBDIRS}; do \ + ${DIR_ENTER}; \ + ${MAKE} ${MFLAGS} clean || exit $$?; \ + ${DIR_LEAVE}; \ + done + + for i in ${DEPS} ${OBJS} ${OBJS_EXTRA} ${LIB_OBJS} ${LIB_OBJS_EXTRA} ${PLUGIN_OBJS} ${PROG} ${PROG_NOINST} ${SHARED_LIB} ${SHARED_LIB_NOINST} ${STATIC_LIB} ${STATIC_LIB_NOINST} ${STATIC_PIC_LIB} ${STATIC_PIC_LIB_NOINST} ${PLUGIN} ${PLUGIN_NOINST} ${CLEAN_LIB} ${MO_FILES} ${CLEAN}; do \ + if test -f $$i -o -d $$i; then \ + if rm -fr $$i; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi \ + done + +distclean: clean + for i in ${SUBDIRS}; do \ + ${DIR_ENTER}; \ + ${MAKE} ${MFLAGS} distclean || exit $$?; \ + ${DIR_LEAVE}; \ + done + + for i in ${DISTCLEAN} .deps *~; do \ + if test -f $$i -o -d $$i; then \ + if rm -fr $$i; then \ + ${DELETE_OK}; \ + else \ + ${DELETE_FAILED}; \ + fi \ + fi \ + done + +DIR_ENTER = printf "@TERM_EL@@TERM_SETAF6@Entering directory @TERM_BOLD@$$i@TERM_SGR0@@TERM_SETAF6@.@TERM_SGR0@\n"; cd $$i || exit $$? +DIR_LEAVE = printf "@TERM_EL@@TERM_SETAF6@Leaving directory @TERM_BOLD@$$i@TERM_SGR0@@TERM_SETAF6@.@TERM_SGR0@\n"; cd .. || exit $$? +DEPEND_STATUS = printf "@TERM_EL@@TERM_SETAF3@Generating dependencies...@TERM_SGR0@\r" +DEPEND_OK = printf "@TERM_EL@@TERM_SETAF2@Successfully generated dependencies.@TERM_SGR0@\n" +DEPEND_FAILED = err=$$?; printf "@TERM_EL@@TERM_SETAF1@Failed to generate dependencies!@TERM_SGR0@\n"; exit $$err +COMPILE_STATUS = printf "@TERM_EL@@TERM_SETAF3@Compiling @TERM_BOLD@$<@TERM_SGR0@@TERM_SETAF3@...@TERM_SGR0@\r" +COMPILE_OK = printf "@TERM_EL@@TERM_SETAF2@Successfully compiled @TERM_BOLD@$<@TERM_SGR0@@TERM_SETAF2@.@TERM_SGR0@\n" +COMPILE_FAILED = err=$$?; printf "@TERM_EL@@TERM_SETAF1@Failed to compile @TERM_BOLD@$<@TERM_SGR0@@TERM_SETAF1@!@TERM_SGR0@\n"; exit $$err +COMPILE_LIB_STATUS = printf "@TERM_EL@@TERM_SETAF3@Compiling @TERM_BOLD@$<@TERM_SGR0@@TERM_SETAF3@ (lib)...@TERM_SGR0@\r" +COMPILE_LIB_OK = printf "@TERM_EL@@TERM_SETAF2@Successfully compiled @TERM_BOLD@$<@TERM_SGR0@@TERM_SETAF2@ (lib).@TERM_SGR0@\n" +COMPILE_LIB_FAILED = err=$$?; printf "@TERM_EL@@TERM_SETAF1@Failed to compile @TERM_BOLD@$<@TERM_SGR0@@TERM_SETAF1@ (lib)!@TERM_SGR0@\n"; exit $$err +COMPILE_PLUGIN_STATUS = printf "@TERM_EL@@TERM_SETAF3@Compiling @TERM_BOLD@$<@TERM_SGR0@@TERM_SETAF3@ (plugin)...@TERM_SGR0@\r" +COMPILE_PLUGIN_OK = printf "@TERM_EL@@TERM_SETAF2@Successfully compiled @TERM_BOLD@$<@TERM_SGR0@@TERM_SETAF2@ (plugin).@TERM_SGR0@\n" +COMPILE_PLUGIN_FAILED = err=$$?; printf "@TERM_EL@@TERM_SETAF1@Failed to compile @TERM_BOLD@$<@TERM_SGR0@@TERM_SETAF1@ (plugin)!@TERM_SGR0@\n"; exit $$err +LINK_STATUS = printf "@TERM_EL@@TERM_SETAF3@Linking @TERM_BOLD@$@@TERM_SGR0@@TERM_SETAF3@...@TERM_SGR0@\r" +LINK_OK = printf "@TERM_EL@@TERM_SETAF2@Successfully linked @TERM_BOLD@$@@TERM_SGR0@@TERM_SETAF2@.@TERM_SGR0@\n" +LINK_FAILED = err=$$?; printf "@TERM_EL@@TERM_SETAF1@Failed to link @TERM_BOLD@$@@TERM_SGR0@@TERM_SETAF1@!@TERM_SGR0@\n"; exit $$err +INSTALL_STATUS = printf "@TERM_EL@@TERM_SETAF3@Installing @TERM_BOLD@$$i@TERM_SGR0@@TERM_SETAF3@...@TERM_SGR0@\r" +INSTALL_OK = printf "@TERM_EL@@TERM_SETAF2@Successfully installed @TERM_BOLD@$$i@TERM_SGR0@@TERM_SETAF2@.@TERM_SGR0@\n" +INSTALL_FAILED = err=$$?; printf "@TERM_EL@@TERM_SETAF1@Failed to install @TERM_BOLD@$$i@TERM_SGR0@@TERM_SETAF1@!@TERM_SGR0@\n"; exit $$err +DELETE_OK = printf "@TERM_EL@@TERM_SETAF4@Deleted @TERM_BOLD@$$i@TERM_SGR0@@TERM_SETAF4@.@TERM_SGR0@\n" +DELETE_FAILED = err=$$?; printf "@TERM_EL@@TERM_SETAF1@Failed to delete @TERM_BOLD@$$i@TERM_SGR0@@TERM_SETAF1@!@TERM_SGR0@\n"; exit $$err + +include .deps diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..a14b772 --- /dev/null +++ b/configure.ac @@ -0,0 +1,52 @@ +AC_INIT(JubJub, 0.1, florob@babelmonkeys.de) +AC_CONFIG_SRCDIR(src) + +AC_CHECK_TOOL(OBJFW_CONFIG, objfw-config) +AS_IF([test x"$OBJFW_CONFIG" = x""], [ + AC_MSG_ERROR(You need ObjFW and objfw-config installed!) +]) + +test x"$OBJC" = x"" && OBJC="$($OBJFW_CONFIG --objc)" + +AC_LANG([Objective C]) +AC_PROG_OBJC +AC_PROG_OBJCPP +AC_PROG_LN_S +AC_PROG_INSTALL + +CPP="$OBJCPP" +CPPFLAGS="$CPPFLAGS $OBJCPPFLAGS $($OBJFW_CONFIG --cppflags)" +OBJCFLAGS="$OBJCFLAGS -Wall $($OBJFW_CONFIG --objcflags)" +LDFLAGS="$LDFLAGS $($OBJFW_CONFIG --ldflags)" +LIBS="$LIBS $($OBJFW_CONFIG --libs)" + +AC_CHECK_LIB(objxmpp, main, [ + LIBS="$LIBS -lobjxmpp" +], [ + AC_MSG_ERROR(ObjXMPP is required!) +]) + +PKG_CHECK_MODULES(GTK, [gtk+-3.0], [ + CPPFLAGS="$CPPFLAGS $GTK_CFLAGS" + LIBS="$LIBS $GTK_LIBS" +], [ + AC_MSG_ERROR(You need at least libgtk 3.0 installed!) +]) + +AC_PATH_TOOL(AR, ar) + +BUILDSYS_INIT +BUILDSYS_TOUCH_DEPS + +dnl We don't call AC_PROG_CPP, but only AC_PROG_OBJCPP and set CPP to OBJCPP +dnl and add OBJCPPFLAGS to CPPFLAGS, thus we need to AC_SUBST these ourself. +AC_SUBST(CPP) +AC_SUBST(CPPFLAGS) + +AC_CONFIG_FILES(buildsys.mk) +dnl AC_CONFIG_FILES([buildsys.mk extra.mk]) + + +AC_SUBST(PACKAGE, JubJub) +AC_CONFIG_HEADERS(config.h) +AC_OUTPUT diff --git a/data/gtk/roster.ui b/data/gtk/roster.ui new file mode 100644 index 0000000..b2e05df --- /dev/null +++ b/data/gtk/roster.ui @@ -0,0 +1,284 @@ + + + + + + + + + + + + + chat + Free for Chat + + + available + Online + + + away + Away + + + xa + Extended Away + + + dnd + Do Not Disturb + + + unavailable + Offline + + + + + + + + + + + + + False + JubJub + 300 + + + + True + False + vertical + + + True + False + + + True + False + _Datei + True + + + True + False + + + gtk-new + True + False + True + True + + + + + gtk-open + True + False + True + True + + + + + gtk-save + True + False + True + True + + + + + gtk-save-as + True + False + True + True + + + + + True + False + + + + + gtk-quit + True + False + True + True + + + + + + + + + + True + False + _Bearbeiten + True + + + True + False + + + gtk-cut + True + False + True + True + + + + + gtk-copy + True + False + True + True + + + + + gtk-paste + True + False + True + True + + + + + gtk-delete + True + False + True + True + + + + + + + + + True + False + _Ansicht + True + + + + + True + False + _Hilfe + True + + + True + False + + + gtk-about + True + False + True + True + + + + + + + + + False + True + 0 + + + + + True + True + in + + + True + True + RosterTreeStore + 0 + + + + + + Name + + + + 0 + + + + + + + JID + + + + 1 + + + + + + + + + True + True + 1 + + + + + True + False + PresenceListStore + True + 1 + 0 + unavailable + + + False + False + + + + + False + True + 2 + + + + + + diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..6781b98 --- /dev/null +++ b/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/m4/buildsys.m4 b/m4/buildsys.m4 new file mode 100644 index 0000000..969978e --- /dev/null +++ b/m4/buildsys.m4 @@ -0,0 +1,192 @@ +dnl +dnl Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 +dnl Jonathan Schleifer +dnl +dnl https://webkeks.org/git/?p=buildsys.git +dnl +dnl Permission to use, copy, modify, and/or distribute this software for any +dnl purpose with or without fee is hereby granted, provided that the above +dnl copyright notice and this permission notice is present in all copies. +dnl +dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +dnl AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +dnl IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +dnl ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +dnl LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +dnl INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +dnl CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +dnl ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +dnl POSSIBILITY OF SUCH DAMAGE. +dnl + +AC_DEFUN([BUILDSYS_INIT], [ + AC_SUBST(CC_DEPENDS, $GCC) + AC_SUBST(CXX_DEPENDS, $GXX) + AC_SUBST(OBJC_DEPENDS, $GOBJC) + AC_SUBST(OBJCXX_DEPENDS, $GOBJCXX) + + AC_PATH_PROG(TPUT, tput) + + AS_IF([test x"$TPUT" != x""], [ + if x=$($TPUT el 2>/dev/null); then + AC_SUBST(TERM_EL, "$x") + else + AC_SUBST(TERM_EL, "$($TPUT ce 2>/dev/null)") + fi + + if x=$($TPUT sgr0 2>/dev/null); then + AC_SUBST(TERM_SGR0, "$x") + else + AC_SUBST(TERM_SGR0, "$($TPUT me 2>/dev/null)") + fi + + if x=$($TPUT bold 2>/dev/null); then + AC_SUBST(TERM_BOLD, "$x") + else + AC_SUBST(TERM_BOLD, "$($TPUT md 2>/dev/null)") + fi + + if x=$($TPUT setaf 1 2>/dev/null); then + AC_SUBST(TERM_SETAF1, "$x") + AC_SUBST(TERM_SETAF2, "$($TPUT setaf 2 2>/dev/null)") + AC_SUBST(TERM_SETAF3, "$($TPUT setaf 3 2>/dev/null)") + AC_SUBST(TERM_SETAF4, "$($TPUT setaf 4 2>/dev/null)") + AC_SUBST(TERM_SETAF6, "$($TPUT setaf 6 2>/dev/null)") + else + AC_SUBST(TERM_SETAF1, "$($TPUT AF 1 2>/dev/null)") + AC_SUBST(TERM_SETAF2, "$($TPUT AF 2 2>/dev/null)") + AC_SUBST(TERM_SETAF3, "$($TPUT AF 3 2>/dev/null)") + AC_SUBST(TERM_SETAF4, "$($TPUT AF 4 2>/dev/null)") + AC_SUBST(TERM_SETAF6, "$($TPUT AF 6 2>/dev/null)") + fi + ], [ + AC_SUBST(TERM_EL, '\033\133K') + AC_SUBST(TERM_SGR0, '\033\133m') + AC_SUBST(TERM_BOLD, '\033\1331m') + AC_SUBST(TERM_SETAF1, '\033\13331m') + AC_SUBST(TERM_SETAF2, '\033\13332m') + AC_SUBST(TERM_SETAF3, '\033\13333m') + AC_SUBST(TERM_SETAF4, '\033\13334m') + AC_SUBST(TERM_SETAF6, '\033\13336m') + ]) +]) + +AC_DEFUN([BUILDSYS_PROG_IMPLIB], [ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_MSG_CHECKING(whether we need an implib) + case "$host_os" in + cygwin* | mingw*) + AC_MSG_RESULT(yes) + PROG_IMPLIB_NEEDED='yes' + PROG_IMPLIB_LDFLAGS='-Wl,-export-all-symbols,--out-implib,lib${PROG}.a' + ;; + *) + AC_MSG_RESULT(no) + PROG_IMPLIB_NEEDED='no' + PROG_IMPLIB_LDFLAGS='' + ;; + esac + + AC_SUBST(PROG_IMPLIB_NEEDED) + AC_SUBST(PROG_IMPLIB_LDFLAGS) +]) + +AC_DEFUN([BUILDSYS_SHARED_LIB], [ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_MSG_CHECKING(for shared library system) + case "$host_os" in + darwin*) + AC_MSG_RESULT(Darwin) + LIB_CFLAGS='-fPIC -DPIC' + LIB_LDFLAGS='-dynamiclib -current_version ${LIB_MAJOR}.${LIB_MINOR} -compatibility_version ${LIB_MAJOR}' + LIB_PREFIX='lib' + LIB_SUFFIX='.dylib' + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + PLUGIN_CFLAGS='-fPIC -DPIC' + PLUGIN_LDFLAGS='-bundle -undefined dynamic_lookup' + PLUGIN_SUFFIX='.bundle' + INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && install_name_tool -id ${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib && ${LN_S} -f $${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib ${DESTDIR}${libdir}/$$i' + UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.dylib ${DESTDIR}${libdir}/$${i%.dylib}.${LIB_MAJOR}.${LIB_MINOR}.dylib' + CLEAN_LIB='' + ;; + solaris*) + AC_MSG_RESULT(Solaris) + LIB_CFLAGS='-fPIC -DPIC' + LIB_LDFLAGS='-shared -Wl,-soname=${SHARED_LIB}.${LIB_MAJOR}.${LIB_MINOR}' + LIB_PREFIX='lib' + LIB_SUFFIX='.so' + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + PLUGIN_CFLAGS='-fPIC -DPIC' + PLUGIN_LDFLAGS='-shared' + PLUGIN_SUFFIX='.so' + INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR} && rm -f ${DESTDIR}${libdir}/$$i && ${LN_S} $$i.${LIB_MAJOR}.${LIB_MINOR} ${DESTDIR}${libdir}/$$i' + UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}' + CLEAN_LIB='' + ;; + openbsd* | mirbsd*) + AC_MSG_RESULT(OpenBSD) + LIB_CFLAGS='-fPIC -DPIC' + LIB_LDFLAGS='-shared' + LIB_PREFIX='lib' + LIB_SUFFIX='.so.${LIB_MAJOR}.${LIB_MINOR}' + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + PLUGIN_CFLAGS='-fPIC -DPIC' + PLUGIN_LDFLAGS='-shared' + PLUGIN_SUFFIX='.so' + INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i' + UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i' + CLEAN_LIB='' + ;; + cygwin* | mingw*) + AC_MSG_RESULT(Win32) + LIB_CFLAGS='' + LIB_LDFLAGS='-shared -Wl,--out-implib,${SHARED_LIB}.a' + LIB_PREFIX='lib' + LIB_SUFFIX='.dll' + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + PLUGIN_CFLAGS='' + PLUGIN_LDFLAGS='-shared' + PLUGIN_SUFFIX='.dll' + INSTALL_LIB='&& ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/$$i && ${INSTALL} -m 755 $$i.a ${DESTDIR}${libdir}/$$i.a' + UNINSTALL_LIB='&& rm -f ${DESTDIR}${bindir}/$$i ${DESTDIR}${libdir}/$$i.a' + CLEAN_LIB='${SHARED_LIB}.a' + ;; + *) + AC_MSG_RESULT(GNU) + LIB_CFLAGS='-fPIC -DPIC' + LIB_LDFLAGS='-shared -Wl,-soname=${SHARED_LIB}.${LIB_MAJOR}' + LIB_PREFIX='lib' + LIB_SUFFIX='.so' + LDFLAGS_RPATH='-Wl,-rpath,${libdir}' + PLUGIN_CFLAGS='-fPIC -DPIC' + PLUGIN_LDFLAGS='-shared' + PLUGIN_SUFFIX='.so' + INSTALL_LIB='&& ${INSTALL} -m 755 $$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0 && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} && ${LN_S} -f $$i.${LIB_MAJOR}.${LIB_MINOR}.0 ${DESTDIR}${libdir}/$$i' + UNINSTALL_LIB='&& rm -f ${DESTDIR}${libdir}/$$i ${DESTDIR}${libdir}/$$i.${LIB_MAJOR} ${DESTDIR}${libdir}/$$i.${LIB_MAJOR}.${LIB_MINOR}.0' + CLEAN_LIB='' + ;; + esac + + AC_SUBST(LIB_CFLAGS) + AC_SUBST(LIB_LDFLAGS) + AC_SUBST(LIB_PREFIX) + AC_SUBST(LIB_SUFFIX) + AC_SUBST(LDFLAGS_RPATH) + AC_SUBST(PLUGIN_CFLAGS) + AC_SUBST(PLUGIN_LDFLAGS) + AC_SUBST(PLUGIN_SUFFIX) + AC_SUBST(INSTALL_LIB) + AC_SUBST(UNINSTALL_LIB) + AC_SUBST(CLEAN_LIB) +]) + +AC_DEFUN([BUILDSYS_TOUCH_DEPS], [ + ${as_echo:="echo"} ${as_me:="configure"}": touching .deps files" + for i in $(find . -name Makefile); do + DEPSFILE="$(dirname $i)/.deps" + test -f "$DEPSFILE" && rm "$DEPSFILE" + touch -t 0001010000 "$DEPSFILE" + done +]) diff --git a/src/core/main.m b/src/core/main.m new file mode 100644 index 0000000..e40a02f --- /dev/null +++ b/src/core/main.m @@ -0,0 +1,57 @@ +#import +#import + +#import "JubGtkUI.h" + +@interface AppDelegate: OFObject + +{ + XMPPConnection *connection; + XMPPRoster *roster; + id ui; +} +@end + +OF_APPLICATION_DELEGATE(AppDelegate) + +@implementation AppDelegate +- (void)applicationDidFinishLaunching +{ + ui = [[JubGtkUI alloc] init]; + + connection = [[XMPPConnection alloc] init]; + [connection addDelegate: self]; + + connection.domain = @"localhost"; + connection.username = @"alice"; + connection.password = @"test"; + + [connection connect]; + [connection handleConnection]; + + roster = [[XMPPRoster alloc] initWithConnection: connection]; + [roster addDelegate: [ui rosterDelegate]]; + + [ui startUIThread]; +} + +- (void)connection: (XMPPConnection*)conn_ + wasBoundToJID: (XMPPJID*)jid +{ + of_log(@"Bound to JID: %@", [jid fullJID]); + + [roster requestRoster]; +} + +- (void)connection: (XMPPConnection*)conn + didReceiveElement: (OFXMLElement*)element +{ + of_log(@"In: %@", element); +} + +- (void)connection: (XMPPConnection*)conn + didSendElement: (OFXMLElement*)element +{ + of_log(@"Out: %@", element); +} +@end diff --git a/src/gui/common/JubUI.h b/src/gui/common/JubUI.h new file mode 100644 index 0000000..3fd08b3 --- /dev/null +++ b/src/gui/common/JubUI.h @@ -0,0 +1,6 @@ +#import + +@protocol JubUI +- (void)startUIThread; +- (id)rosterDelegate; +@end diff --git a/src/gui/gtk/JubGObjectMap.h b/src/gui/gtk/JubGObjectMap.h new file mode 100644 index 0000000..fef08a1 --- /dev/null +++ b/src/gui/gtk/JubGObjectMap.h @@ -0,0 +1,86 @@ +#import +#include + +static void *copy(void *value) +{ + return [(id)value copy]; +} + +static void release(void *value) +{ + [(id)value release]; +} + +static uint32_t hash(void *value) +{ + return [(id)value hash]; +} + +static BOOL equal(void *value1, void *value2) +{ + return [(id)value1 isEqual: (id)value2]; +} + +static void *g_retain(void *value) +{ + return g_object_ref(value); +} + +static void g_release(void *value) +{ + g_object_unref(value); +} + +static void *default_retain(void *value) +{ + return value; +} + +static uint32_t default_hash(void *value) +{ +#define NUM (sizeof(void*)/sizeof(uint32_t)) + int i; + uint32_t hash = 0; + union { + void *v; + uint32_t i[NUM]; + } u = { value }; + + for (i = 0; i < NUM; i++) + hash ^= u.i[i]; + + return hash; +#undef NUM +} + +static BOOL default_equal(void *value1, void *value2) +{ + return (value1 == value2); +} + + +static void rowref_release(void *value) +{ + gtk_tree_row_reference_free(value); +} + +static of_map_table_functions_t keyFunctions = { + .retain = copy, + .release = release, + .hash = hash, + .equal = equal +}; + +static of_map_table_functions_t gObjectFunctions __attribute__((unused)) = { + .retain = g_retain, + .release = g_release, + .hash = default_hash, + .equal = default_equal +}; + +static of_map_table_functions_t rowRefFunctions = { + .retain = default_retain, + .release = rowref_release, + .hash = default_hash, + .equal = default_equal +}; diff --git a/src/gui/gtk/JubGtkUI.h b/src/gui/gtk/JubGtkUI.h new file mode 100644 index 0000000..31e6902 --- /dev/null +++ b/src/gui/gtk/JubGtkUI.h @@ -0,0 +1,12 @@ +#import +#include + +#import "JubUI.h" + +@interface JubGtkUI: OFObject +{ + GtkTreeStore *roster_model; + OFMapTable *groupMap; + OFMutableDictionary *contactMap; +} +@end diff --git a/src/gui/gtk/JubGtkUI.m b/src/gui/gtk/JubGtkUI.m new file mode 100644 index 0000000..48278b8 --- /dev/null +++ b/src/gui/gtk/JubGtkUI.m @@ -0,0 +1,279 @@ +#import +#include + +#import "JubGtkUI.h" +#import "JubGObjectMap.h" + +void on_roster_window_destroy(GObject *object, gpointer user_data) +{ + gtk_main_quit(); +} + +@implementation JubGtkUI +- init +{ + self = [super init]; + + @try { + groupMap = [[OFMapTable alloc] + initWithKeyFunctions: keyFunctions + valueFunctions: rowRefFunctions]; + contactMap = [[OFMutableDictionary alloc] init]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + + [groupMap release]; + [contactMap release]; + + if (roster_model) + g_object_unref(roster_model); + + [super dealloc]; +} + +- (void)startUIThread +{ + int *argc; + char ***argv; + + GtkBuilder *builder; + GtkWidget *roster_window; + + [[OFApplication sharedApplication] getArgumentCount: &argc + andArgumentValues: &argv]; + + gtk_init(argc, argv); + + builder = gtk_builder_new(); + gtk_builder_add_from_file(builder, "data/gtk/roster.ui", NULL); + + roster_window = + GTK_WIDGET(gtk_builder_get_object(builder, "RosterWindow")); + + roster_model = + GTK_TREE_STORE(gtk_builder_get_object(builder, "RosterTreeStore")); + + gtk_builder_connect_signals(builder, NULL); + g_object_unref(G_OBJECT(builder)); + + gtk_widget_show(roster_window); + + [[OFThread threadWithBlock: ^(void){ + gtk_main(); + [OFApplication terminate]; + + return nil; + }] start]; +} + + +- (id)rosterDelegate +{ + return self; +} + +/* Roster Delegate methods */ +struct add_roster_item_param { + OFString *group; + OFString *name; + OFString *jid; + OFMapTable *groupMap; + OFMapTable *contactRows; + GtkTreeStore *roster_model; +}; + +static gboolean add_roster_item(gpointer user_data) +{ + struct add_roster_item_param *params = user_data; + GtkTreeIter group_iter, contact_iter; + GtkTreeRowReference *group_ref, *contact_ref; + GtkTreePath *group_path, *contact_path; + + group_ref = [params->groupMap valueForKey: params->group]; + + if (!group_ref) { + // Create new group row + gtk_tree_store_append(params->roster_model, &group_iter, NULL); + gtk_tree_store_set(params->roster_model, &group_iter, + 0, [params->group UTF8String], -1); + + group_path = gtk_tree_model_get_path(GTK_TREE_MODEL( + params->roster_model), &group_iter); + + group_ref = gtk_tree_row_reference_new(GTK_TREE_MODEL( + params->roster_model), group_path); + + [params->groupMap setValue: group_ref + forKey: params->group]; + } else { + // Get iter for existing group row + group_path = gtk_tree_row_reference_get_path(group_ref); + + gtk_tree_model_get_iter(GTK_TREE_MODEL(params->roster_model), + &group_iter, group_path); + } + gtk_tree_path_free(group_path); + + // Create new contact row + gtk_tree_store_append(params->roster_model, &contact_iter, &group_iter); + gtk_tree_store_set(params->roster_model, &contact_iter, + 0, [params->name UTF8String], 1, [params->jid UTF8String], -1); + + contact_path = gtk_tree_model_get_path(GTK_TREE_MODEL( + params->roster_model), &contact_iter); + + contact_ref = gtk_tree_row_reference_new(GTK_TREE_MODEL( + params->roster_model), contact_path); + + gtk_tree_path_free(contact_path); + + [params->contactRows setValue: contact_ref + forKey: params->group]; + + [params->group release]; + [params->name release]; + [params->jid release]; + [params->groupMap release]; + [params->contactRows release]; + g_object_unref(params->roster_model); + free(params); + + return FALSE; +} + +- (void)rosterWasReceived: (XMPPRoster*)roster_ +{ + [[roster_ rosterItems] enumerateKeysAndObjectsUsingBlock: + ^(OFString *bareJID, XMPPRosterItem *item, BOOL *stop) { + OFArray *groups; + OFMapTable *contactRows = [OFMapTable + mapTableWithKeyFunctions: keyFunctions + valueFunctions: rowRefFunctions]; + + [contactMap setObject: contactRows + forKey: bareJID]; + + if (item.groups != nil) + groups = item.groups; + else + groups = @[@"General"]; + + for (OFString *group in groups) { + struct add_roster_item_param *params = + malloc(sizeof(*params)); + params->group = [group retain]; + params->name = [item.name retain]; + params->jid = [bareJID retain]; + params->groupMap = [groupMap retain]; + params->contactRows = [contactRows retain]; + params->roster_model = g_object_ref(roster_model); + g_idle_add(add_roster_item, params); + } + }]; +} + +struct remove_roster_item_param { + OFString *group; + OFMapTable *groupMap; + OFMapTable *contactRows; + GtkTreeStore *roster_model; +}; + +static gboolean remove_roster_item(gpointer user_data) +{ + struct remove_roster_item_param *params = user_data; + GtkTreeIter contact_iter, group_iter; + GtkTreePath *contact_path, *group_path; + GtkTreeRowReference *contact_ref, *group_ref; + + contact_ref = [params->contactRows valueForKey: params->group]; + contact_path = gtk_tree_row_reference_get_path(contact_ref); + gtk_tree_model_get_iter(GTK_TREE_MODEL(params->roster_model), + &contact_iter, contact_path); + + gtk_tree_store_remove(params->roster_model, &contact_iter); + + group_ref = [params->groupMap valueForKey: params->group]; + group_path = gtk_tree_row_reference_get_path(group_ref); + gtk_tree_model_get_iter(GTK_TREE_MODEL(params->roster_model), + &group_iter, group_path); + + if (!gtk_tree_model_iter_has_child(GTK_TREE_MODEL(params->roster_model), + &group_iter)) { + gtk_tree_store_remove(params->roster_model, &group_iter); + [params->groupMap removeValueForKey: params->group]; + } + + gtk_tree_path_free(group_path); + + [params->group release]; + [params->groupMap release]; + [params->contactRows release]; + g_object_unref(params->roster_model); + free(params); + + return FALSE; +} + +- (void)roster: (XMPPRoster*)roster_ + didReceiveRosterItem: (XMPPRosterItem*)item +{ + OFArray *groups; + XMPPRosterItem *oldItem = + [roster_.rosterItems objectForKey: [item.JID bareJID]]; + + if (oldItem) { + if (oldItem.groups != nil) + groups = oldItem.groups; + else + groups = @[@"General"]; + + for (OFString *group in groups) { + struct remove_roster_item_param *params = + malloc(sizeof(*params)); + params->group = [group retain]; + params->contactRows = [[contactMap objectForKey: + [oldItem.JID bareJID]] retain]; + params->groupMap = [groupMap retain]; + params->roster_model = g_object_ref(roster_model); + g_idle_add(remove_roster_item, params); + } + + [contactMap removeObjectForKey: [item.JID bareJID]]; + } + + if (![item.subscription isEqual: @"remove"]) { + OFMapTable *contactRows = [OFMapTable + mapTableWithKeyFunctions: keyFunctions + valueFunctions: rowRefFunctions]; + + [contactMap setObject: contactRows + forKey: [item.JID bareJID]]; + + if (item.groups != nil) + groups = item.groups; + else + groups = @[@"General"]; + + for (OFString *group in groups) { + struct add_roster_item_param *params = + malloc(sizeof(*params)); + params->group = [group retain]; + params->name = [item.name retain]; + params->jid = [[item.JID bareJID] retain]; + params->groupMap = [groupMap retain]; + params->contactRows = [contactRows retain]; + params->roster_model = g_object_ref(roster_model); + g_idle_add(add_roster_item, params); + } + } +} +@end