From 0b7693d077936cffda6c283111e3a780c0078fde Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Tue, 5 Jul 2011 00:18:43 +0300 Subject: [PATCH] * guilify mu; first steps, and a new toy called 'muile' --- Makefile.am | 9 +- configure.ac | 15 ++ libmuguile/Makefile.am | 38 ++++ libmuguile/mu-msg-guile.c | 419 ++++++++++++++++++++++++++++++++++++++ libmuguile/mu-msg-guile.h | 37 ++++ src/mu-msg.h | 8 +- src/mu-str.c | 1 - toys/Makefile.am | 4 + toys/muile/Makefile.am | 35 ++++ toys/muile/muile.cc | 31 +++ 10 files changed, 589 insertions(+), 8 deletions(-) create mode 100644 libmuguile/Makefile.am create mode 100644 libmuguile/mu-msg-guile.c create mode 100644 libmuguile/mu-msg-guile.h create mode 100644 toys/muile/Makefile.am create mode 100644 toys/muile/muile.cc diff --git a/Makefile.am b/Makefile.am index 2c89d631..6cb57b5f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,14 @@ else widgets= endif -SUBDIRS=m4 man src $(widgets) contrib toys +if HAVE_GUILE +guile=libmuguile +else +guile= +endif + +SUBDIRS=m4 man src $(widgets) $(guile) contrib toys + ACLOCAL_AMFLAGS=-I m4 diff --git a/configure.ac b/configure.ac index cbe65b71..b26bc05f 100644 --- a/configure.ac +++ b/configure.ac @@ -204,6 +204,15 @@ AM_CONDITIONAL(HAVE_GIO, [test "x$have_gio" = "xyes"]) # should we build the widgets/ dir? AM_CONDITIONAL(BUILD_WIDGETS, [test "x$have_webkit" = "xyes" -a "x$have_gio" = "xyes"]) + +# check for guile +AC_PATH_PROG(GUILE, [guile-config], [], [$PATH]) + AS_IF([test "x$GUILE" != "x"], + [GUILE_CFLAGS=`$GUILE compile`; GUILE_LIBS=`$GUILE link`]) +AM_CONDITIONAL(HAVE_GUILE, [test "$xGUILE" != "x"]) +AC_SUBST(GUILE_LIBS) +AC_SUBST(GUILE_CFLAGS) + # check for xdg-open AS_IF([test "x$buildgui"="xyes"],[ AC_PATH_PROG(XDGOPEN, [xdg-open], [], [$PATH]) @@ -228,9 +237,11 @@ Makefile src/Makefile src/tests/Makefile widgets/Makefile +libmuguile/Makefile toys/Makefile toys/mug/Makefile toys/mug2/Makefile +toys/muile/Makefile man/Makefile m4/Makefile contrib/Makefile @@ -264,6 +275,10 @@ if test "x$have_webkit" = "xyes"; then echo "Webkit version : $webkit_version" fi +if test "x$GUILE" != "x"; then +echo "Guile version : `$GUILE --version 2>&1`" +fi + echo echo "Build unit tests (glib >= 2.22) : $have_gtest" echo "Build 'mug' toy-ui (requires GTK+) : $buildgui" diff --git a/libmuguile/Makefile.am b/libmuguile/Makefile.am new file mode 100644 index 00000000..666028b4 --- /dev/null +++ b/libmuguile/Makefile.am @@ -0,0 +1,38 @@ +## Copyright (C) 2011 Dirk-Jan C. Binnema +## +## 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 +## t he Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +# enforce compiling this dir first before decending into tests/ +SUBDIRS= . +INCLUDES=-I${top_srcdir}/src ${GUILE_CFLAGS} ${GLIB_CFLAGS} + +# don't use -Werror, as it might break on other compilers +# use -Wno-unused-parameters, because some callbacks may not +# really need all the params they get +AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement +AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter + +noinst_LTLIBRARIES= \ + libmuguile.la + +libmuguile_la_SOURCES= \ + mu-msg-guile.c + +libmuguile_la_LIBADD= \ + ${top_builddir}/src/libmu.la \ + ${GUILE_LIBS} + diff --git a/libmuguile/mu-msg-guile.c b/libmuguile/mu-msg-guile.c new file mode 100644 index 00000000..dfabb00c --- /dev/null +++ b/libmuguile/mu-msg-guile.c @@ -0,0 +1,419 @@ +/* +** Copyright (C) 2011 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include +#include + +struct _MuMsgWrapper { + MuMsg *_msg; + gboolean _unrefme; +}; +typedef struct _MuMsgWrapper MuMsgWrapper; + +static long MSG_TAG; + + +static SCM +msg_make_from_file (SCM path) +{ + const char* msgpath; + MuMsgWrapper *msgwrap; + + msgpath = scm_to_utf8_string (path); + + msgwrap = scm_gc_malloc (sizeof (MuMsgWrapper), "msg"); + msgwrap->_msg = mu_msg_new_from_file (msgpath, NULL, NULL); + msgwrap->_unrefme = FALSE; + + SCM_RETURN_NEWSMOB (MSG_TAG, msgwrap); +} + + +static SCM +msg_str_field (SCM msg_smob, MuMsgFieldId mfid) +{ + const char *val; + MuMsgWrapper *msgwrap; + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + val = mu_msg_get_field_string(msgwrap->_msg, mfid); + + return val ? scm_from_utf8_string(val) : SCM_UNDEFINED; +} + +static gint64 +msg_num_field (SCM msg_smob, MuMsgFieldId mfid) +{ + MuMsgWrapper *msgwrap; + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + return mu_msg_get_field_numeric(msgwrap->_msg, mfid); +} + + +static SCM +msg_date (SCM msg_smob) +{ + return scm_from_unsigned_integer + (msg_num_field (msg_smob, MU_MSG_FIELD_ID_DATE)); +} + +static SCM +msg_size (SCM msg_smob) +{ + return scm_from_unsigned_integer + (msg_num_field (msg_smob, MU_MSG_FIELD_ID_SIZE)); +} + + +static SCM +msg_prio (SCM msg_smob) +{ + MuMsgPrio prio; + MuMsgWrapper *msgwrap; + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + prio = mu_msg_get_prio (msgwrap->_msg); + + switch (prio) { + case MU_MSG_PRIO_LOW: return scm_from_utf8_symbol ("low"); + case MU_MSG_PRIO_NORMAL: return scm_from_utf8_symbol ("normal"); + case MU_MSG_PRIO_HIGH: return scm_from_utf8_symbol ("high"); + default: + g_return_val_if_reached (SCM_UNDEFINED); + } +} + + +struct _FlagData { + MuMsgFlags flags; + SCM lst; +}; +typedef struct _FlagData FlagData; + + +static void +check_flag (MuMsgFlags flag, FlagData *fdata) +{ + if (fdata->flags & flag) { + SCM item; + item = scm_list_1 (scm_from_utf8_symbol(mu_msg_flag_name(flag))); + fdata->lst = scm_append_x (scm_list_2(fdata->lst, item)); + } +} + +static SCM +msg_flags (SCM msg_smob) +{ + MuMsgWrapper *msgwrap; + FlagData fdata; + + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + fdata.flags = mu_msg_get_flags (msgwrap->_msg); + fdata.lst = SCM_EOL; + mu_msg_flags_foreach ((MuMsgFlagsForeachFunc)check_flag, + &fdata); + + return fdata.lst; +} + + +static SCM +msg_subject (SCM msg_smob) +{ + return msg_str_field (msg_smob, MU_MSG_FIELD_ID_SUBJECT); +} + +static SCM +msg_from (SCM msg_smob) +{ + return msg_str_field (msg_smob, MU_MSG_FIELD_ID_FROM); +} + + +struct _EachContactData { + SCM lst; + MuMsgContactType ctype; +}; +typedef struct _EachContactData EachContactData; + +static void +contacts_to_list (MuMsgContact *contact, EachContactData *ecdata) +{ + if (mu_msg_contact_type (contact) == ecdata->ctype) { + SCM item; + const char *addr, *name; + addr = mu_msg_contact_address(contact); + name = mu_msg_contact_name(contact); + + item = scm_list_1 + (scm_list_2 ( + name ? scm_from_utf8_string(name) : SCM_UNDEFINED, + addr ? scm_from_utf8_string(addr) : SCM_UNDEFINED)); + + ecdata->lst = scm_append_x (scm_list_2(ecdata->lst, item)); + } +} + + +static SCM +contact_list_field (SCM msg_smob, MuMsgFieldId mfid) +{ + MuMsgWrapper *msgwrap; + EachContactData ecdata; + + ecdata.lst = SCM_EOL; + + switch (mfid) { + case MU_MSG_FIELD_ID_TO: ecdata.ctype = MU_MSG_CONTACT_TYPE_TO; break; + case MU_MSG_FIELD_ID_CC: ecdata.ctype = MU_MSG_CONTACT_TYPE_CC; break; + case MU_MSG_FIELD_ID_BCC: ecdata.ctype = MU_MSG_CONTACT_TYPE_BCC; break; + default: g_return_val_if_reached (SCM_UNDEFINED); + } + + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + mu_msg_contact_foreach (msgwrap->_msg, + (MuMsgContactForeachFunc)contacts_to_list, + &ecdata); + return ecdata.lst; +} + + + +static SCM +msg_to (SCM msg_smob) +{ + return contact_list_field (msg_smob, MU_MSG_FIELD_ID_TO); +} + + +static SCM +msg_cc (SCM msg_smob) +{ + return contact_list_field (msg_smob, MU_MSG_FIELD_ID_CC); +} + + +static SCM +msg_bcc (SCM msg_smob) +{ + return contact_list_field (msg_smob, MU_MSG_FIELD_ID_BCC); +} + +static SCM +msg_path (SCM msg_smob) +{ + return msg_str_field (msg_smob, MU_MSG_FIELD_ID_PATH); +} + + +static SCM +msg_maildir (SCM msg_smob) +{ + return msg_str_field (msg_smob, MU_MSG_FIELD_ID_MAILDIR); +} + +static SCM +msg_msgid (SCM msg_smob) +{ + return msg_str_field (msg_smob, MU_MSG_FIELD_ID_MSGID); +} + + + +static SCM +msg_body (SCM msg_smob, SCM html_smob) +{ + MuMsgWrapper *msgwrap; + gboolean html; + const char *val; + + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + html = SCM_UNBNDP(html_smob) ? FALSE : html_smob == SCM_BOOL_T; + + if (html) + val = mu_msg_get_body_html(msgwrap->_msg); + else + val = mu_msg_get_body_text(msgwrap->_msg); + + return val ? scm_from_utf8_string (val) : SCM_UNDEFINED; +} + + +static SCM +msg_header (SCM msg_smob, SCM header_smob) +{ + MuMsgWrapper *msgwrap; + const char *header; + const char *val; + + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + header = scm_to_utf8_string (header_smob); + val = mu_msg_get_header(msgwrap->_msg, header); + + return val ? scm_from_utf8_string(val) : SCM_UNDEFINED; +} + +static SCM +msg_string_list_field (SCM msg_smob, MuMsgFieldId mfid) +{ + MuMsgWrapper *msgwrap; + SCM scmlst; + const GSList *lst; + + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + lst = mu_msg_get_field_string_list (msgwrap->_msg, mfid); + + for (scmlst = SCM_EOL; lst; + lst = g_slist_next(lst)) { + SCM item; + item = scm_list_1 (scm_from_utf8_string((const char*)lst->data)); + scmlst = scm_append_x (scm_list_2(scmlst, item)); + } + + return scmlst; +} + +static SCM +msg_tags (SCM msg_smob) +{ + return msg_string_list_field (msg_smob, MU_MSG_FIELD_ID_TAGS); +} + + +static SCM +msg_references (SCM msg_smob) +{ + return msg_string_list_field (msg_smob, MU_MSG_FIELD_ID_REFS); +} + + + + +static SCM +msg_mark (SCM msg_smob) +{ + MuMsgWrapper *msgwrap; + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + msgwrap->_unrefme = TRUE; + + return SCM_UNSPECIFIED; +} + +static scm_sizet +msg_free (SCM msg_smob) +{ + MuMsgWrapper *msgwrap; + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + if (msgwrap->_unrefme) + mu_msg_unref (msgwrap->_msg); + + return sizeof (MuMsgWrapper); +} + +static int +msg_print (SCM msg_smob, SCM port, scm_print_state * pstate) +{ + MuMsgWrapper *msgwrap; + msgwrap = (MuMsgWrapper*) SCM_CDR(msg_smob); + + scm_puts ("#_msg), + port); + + scm_puts (">", port); + + return 1; +} + + +static void +define_symbols (void) +{ + /* message priority */ + scm_c_define ("high", scm_from_int(MU_MSG_PRIO_HIGH)); + scm_c_define ("low", scm_from_int(MU_MSG_PRIO_LOW)); + scm_c_define ("normal", scm_from_int(MU_MSG_PRIO_NORMAL)); + + /* message flags */ + scm_c_define ("new", scm_from_int(MU_MSG_FLAG_NEW)); + scm_c_define ("passed", scm_from_int(MU_MSG_FLAG_PASSED)); + scm_c_define ("replied", scm_from_int(MU_MSG_FLAG_REPLIED)); + scm_c_define ("seen", scm_from_int(MU_MSG_FLAG_SEEN)); + scm_c_define ("trashed", scm_from_int(MU_MSG_FLAG_TRASHED)); + scm_c_define ("draft", scm_from_int(MU_MSG_FLAG_DRAFT)); + scm_c_define ("flagged", scm_from_int(MU_MSG_FLAG_FLAGGED)); + scm_c_define ("unread", scm_from_int(MU_MSG_FLAG_UNREAD)); + scm_c_define ("signed", scm_from_int(MU_MSG_FLAG_SIGNED)); + scm_c_define ("encrypted", scm_from_int(MU_MSG_FLAG_ENCRYPTED)); + scm_c_define ("has-attach", scm_from_int(MU_MSG_FLAG_HAS_ATTACH)); +} + + + +void* +mu_msg_guile_register (void *data) +{ + MSG_TAG = scm_make_smob_type ("msg", sizeof(MuMsgWrapper)); + + scm_set_smob_mark (MSG_TAG, msg_mark); + scm_set_smob_free (MSG_TAG, msg_free); + scm_set_smob_print (MSG_TAG, msg_print); + + define_symbols (); + + scm_c_define_gsubr ("make-msg-from-file", 1, 0, 0, + &msg_make_from_file); + + scm_c_define_gsubr ("from", 1, 0, 0, &msg_from); + + scm_c_define_gsubr ("subject", 1, 0, 0, &msg_subject); + scm_c_define_gsubr ("path", 1, 0, 0, &msg_path); + scm_c_define_gsubr ("maildir", 1, 0, 0, &msg_maildir); + scm_c_define_gsubr ("message-id", 1, 0, 0, &msg_msgid); + + scm_c_define_gsubr ("date", 1, 0, 0, &msg_date); + scm_c_define_gsubr ("size", 1, 0, 0, &msg_size); + + scm_c_define_gsubr ("body", 1, 1, 0, &msg_body); + scm_c_define_gsubr ("header", 2, 0, 0, &msg_header); + + /* lists */ + scm_c_define_gsubr ("tags", 1, 0, 0, &msg_tags); + scm_c_define_gsubr ("references", 1, 0, 0, &msg_references); + scm_c_define_gsubr ("to", 1, 0, 0, &msg_to); + scm_c_define_gsubr ("cc", 1, 0, 0, &msg_cc); + scm_c_define_gsubr ("bcc", 1, 0, 0, &msg_bcc); + + scm_c_define_gsubr ("priority", 1, 0, 0, &msg_prio); + scm_c_define_gsubr ("flags", 1, 0, 0, &msg_flags); + + + return NULL; +} + + diff --git a/libmuguile/mu-msg-guile.h b/libmuguile/mu-msg-guile.h new file mode 100644 index 00000000..22a1c6ad --- /dev/null +++ b/libmuguile/mu-msg-guile.h @@ -0,0 +1,37 @@ +/* +** Copyright (C) 2011 +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_GUILE_H__ +#define __MU_MSG_GUILE_H__ + +extern "C" { + +/** + * register MuMsg-related functions/smobs with guile; use with + * scm_with_guile + * + * @param data + * + * @return + */ +void* mu_msg_guile_register (void *data); + +} + +#endif /*__MU_MSG_GUILE_H__*/ diff --git a/src/mu-msg.h b/src/mu-msg.h index 3ca3490f..62162143 100644 --- a/src/mu-msg.h +++ b/src/mu-msg.h @@ -77,7 +77,7 @@ MuMsg *mu_msg_new_from_doc (XapianDocument* doc, GError **err) * @return the message with its reference count increased, or NULL in * case of error. */ -MuMsg * mu_msg_ref (MuMsg *msg); +MuMsg *mu_msg_ref (MuMsg *msg); /** * decrease the reference count for this message. if the reference @@ -305,7 +305,7 @@ MuMsgPrio mu_msg_get_prio (MuMsg *msg); * * @return the timestamp or 0 in case of error */ -time_t mu_msg_get_timestamp (MuMsg *msg); +time_t mu_msg_get_timestamp (MuMsg *msg); @@ -334,10 +334,6 @@ const char* mu_msg_get_header (MuMsg *self, const char *header); */ const GSList* mu_msg_get_references (MuMsg *msg); - - - - /** * get the list of tags (ie., X-Label) * diff --git a/src/mu-str.c b/src/mu-str.c index 950a9f8d..233d6912 100644 --- a/src/mu-str.c +++ b/src/mu-str.c @@ -435,7 +435,6 @@ mu_str_subject_normalize (const gchar* str) gchar *last_colon; g_return_val_if_fail (str, NULL); - /* FIXME: improve this */ last_colon = g_strrstr (str, ":"); if (!last_colon) return str; diff --git a/toys/Makefile.am b/toys/Makefile.am index 57debc56..aac6132f 100644 --- a/toys/Makefile.am +++ b/toys/Makefile.am @@ -28,3 +28,7 @@ if BUILD_WIDGETS SUBDIRS += mug2 endif +# for muile, we need guile +if HAVE_GUILE +SUBDIRS += muile +endif diff --git a/toys/muile/Makefile.am b/toys/muile/Makefile.am new file mode 100644 index 00000000..700528e2 --- /dev/null +++ b/toys/muile/Makefile.am @@ -0,0 +1,35 @@ +## Copyright (C) 2011 Dirk-Jan C. Binnema +## +## 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 +## t he Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software Foundation, +## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +include $(top_srcdir)/gtest.mk + +# enforce compiling this dir first before decending into tests/ +INCLUDES=-I${top_srcdir} ${GUILE_CFLAGS} ${GLIB_CFLAGS} + +# don't use -Werror, as it might break on other compilers +# use -Wno-unused-parameters, because some callbacks may not +# really need all the params they get +AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement +AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter + +noinst_PROGRAMS= \ + muile + +muile_SOURCES= \ + muile.cc + +muile_LDFLAGS= \ + ${top_builddir}/libmuguile/libmuguile.la diff --git a/toys/muile/muile.cc b/toys/muile/muile.cc new file mode 100644 index 00000000..7e1d27de --- /dev/null +++ b/toys/muile/muile.cc @@ -0,0 +1,31 @@ +/* +** Copyright (C) 2011 Dirk-Jan C. Binnema +** +** 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 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#include +#include + +int +main (int argc, char *argv[]) +{ + scm_with_guile (&mu_msg_guile_register, NULL); + + scm_shell (argc, argv); + + return 0; +}