Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Titus von der Malsburg
2013-03-17 20:42:44 +01:00
23 changed files with 244 additions and 328 deletions

View File

@ -110,6 +110,11 @@ AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS) AC_SUBST(GLIB_LIBS)
glib_version="`$PKG_CONFIG --modversion glib-2.0`" glib_version="`$PKG_CONFIG --modversion glib-2.0`"
PKG_CHECK_MODULES(GIO,gio-2.0,[have_gio=yes],[have_gio=no])
AC_SUBST(GIO_CFLAGS)
AC_SUBST(GIO_LIBS)
gio_version="`$PKG_CONFIG --modversion gio-2.0`"
# gmime 2.4 or 2.6? # gmime 2.4 or 2.6?
PKG_CHECK_MODULES(GMIME,gmime-2.6,[have_gmime_26=yes],[have_gmime_26=no]) PKG_CHECK_MODULES(GMIME,gmime-2.6,[have_gmime_26=yes],[have_gmime_26=no])
AS_IF([test "x$have_gmime_26" = "xno"],[ AS_IF([test "x$have_gmime_26" = "xno"],[
@ -169,82 +174,28 @@ AC_DEFINE(MU_STORE_SCHEMA_VERSION,["9.9"], ['Schema' version of the database])
############################################################################### ###############################################################################
# we need gtk (2 or 3) for some of the graphical tools # we need GTK+3 for some of the graphical tools
# # use --without-gtk to disable it
AC_ARG_WITH([gui], AC_ARG_ENABLE([gtk],AS_HELP_STRING([--disable-gtk],[Disable GTK+]))
[AS_HELP_STRING([--with-gui=gtk2|gtk3|none])], AS_IF([test "x$enable_gtk" != "xno"],[
[gui=$withval],[gui=auto]) PKG_CHECK_MODULES(GTK,gtk+-3.0,[have_gtk=yes],[have_gtk=no])
AS_IF([test "x$gui" != "xgtk2" -a "x$gui" != "xgtk3" -a "x$gui" != "xnone" \
-a "x$gui" != "xauto"],
AC_MSG_ERROR([the argument for --with-gui= must be either \
gtk2|gtk3|auto|no ($gui)]))
AS_IF([test "x$gui" != "xnone"],[
# check for gtk3
AS_IF([test "x$gui" = "xgtk3"],[
PKG_CHECK_MODULES(GTK,gtk+-3.0,[have_gtk3=yes],[have_gtk3=no])
AC_SUBST(GTK_CFLAGS) AC_SUBST(GTK_CFLAGS)
AC_SUBST(GTK_LIBS) AC_SUBST(GTK_LIBS)
gtk_version="`$PKG_CONFIG --modversion gtk+-3.0`" gtk_version="`$PKG_CONFIG --modversion gtk+-3.0`"])
]) AM_CONDITIONAL(HAVE_GTK,[test "x$have_gtk" = "xyes"])
AS_IF([test "x$gui"="gtk3" -a "x$have_gtk3" = "xno"],
AC_MSG_ERROR([GTK+ 3.x not found]))
# check for gtk2 if we did not find gtk3 already
# (gtk3 is only sought if asked for it explicitly)
AS_IF([test "x$gui" != "xno" -a "x$have_gtk3" != "xyes"],[
PKG_CHECK_MODULES(GTK,gtk+-2.0,[have_gtk2=yes],[have_gtk2=no])
AC_SUBST(GTK_CFLAGS)
AC_SUBST(GTK_LIBS)
gtk_version="`$PKG_CONFIG --modversion gtk+-2.0`"
])
# only an error if we explicitly asked for it
AS_IF([test "x$have_gtk2" = "xno" -a "x$gui" != "xauto"],
AC_MSG_ERROR([GTK+ 2.x not found]))
])
AM_CONDITIONAL(HAVE_GTK,[test "x$have_gtk2" = "xyes" -o "x$have_gtk3" = "xyes" ])
AS_IF([test "x$have_gtk2" = "xyes" -o "x$have_gtk3" = "xyes"],[buildgui=yes],
[buildgui=no])
AS_IF([test "x$have_gtk3" = "xyes"],
[AC_DEFINE_UNQUOTED([HAVE_GTK3],1,[Whether we have GTK+ 3.x])])
# webkit? needed for the fancy web widget # webkit? needed for the fancy web widget
# use --disable-webkit to disable it, even if you have it # use --disable-webkit to disable it, even if you have it
# note; gtk2 and gtk3 imply different webkit versions AC_ARG_ENABLE([webkit],AS_HELP_STRING([--disable-webkit],[Disable webkit]))
build_webkit=no AS_IF([test "x$enable_webkit" != "xno"],[
AC_ARG_ENABLE([webkit], PKG_CHECK_MODULES(WEBKIT,webkitgtk-3.0 >= 1.8.0,[have_webkit=yes],[have_webkit=no])
AS_HELP_STRING([--disable-webkit],[Disable webkit])) AS_IF([test "x$have_webkit" = "xyes"],[
AS_IF([test "x$enable_webkit" != "xno"], [
AS_IF([test "x$have_gtk2" = "xyes"],[
PKG_CHECK_MODULES(WEBKIT,webkit-1.0 >= 1.0.3,[build_webkit=yes],[build_webkit=no])
AS_IF([test "x$build_webkit" = "xyes"],[
webkit_version="`$PKG_CONFIG --modversion webkit-1.0`"])
AC_SUBST(WEBKIT_CFLAGS)
AC_SUBST(WEBKIT_LIBS)])
AS_IF([test "x$have_gtk3" = "xyes"],[
PKG_CHECK_MODULES(WEBKIT,webkitgtk-3.0 >= 1.8.0, [build_webkit=yes],[build_webkit=no])
AS_IF([test "x$build_webkit" = "xyes"],[
webkit_version="`$PKG_CONFIG --modversion webkitgtk-3.0`"]) webkit_version="`$PKG_CONFIG --modversion webkitgtk-3.0`"])
AC_SUBST(WEBKIT_CFLAGS) AC_SUBST(WEBKIT_CFLAGS)
AC_SUBST(WEBKIT_LIBS)]) AC_SUBST(WEBKIT_LIBS)
]) ])
AM_CONDITIONAL(BUILD_WEBKIT, [test "x$build_webkit" = "xyes"]) AM_CONDITIONAL(HAVE_WEBKIT, [test "x$have_webkit" = "xyes"])
AM_CONDITIONAL(BUILD_GUI,[test "x$have_webkit" = "xyes" -a "x$have_gtk" = "xyes"])
# gio is needed for some widget/ things
AS_IF([test "x$buildgui"="xyes"],[
PKG_CHECK_MODULES(GIO,gio-2.0,[have_gio=yes],[have_gio=no])
AS_IF([test "x$have_gio" = "xyes"],[
gio_version="`$PKG_CONFIG --modversion gio-2.0`"])
AC_SUBST(GIO_CFLAGS)
AC_SUBST(GIO_LIBS)
])
AM_CONDITIONAL(HAVE_GIO, [test "x$have_gio" = "xyes"])
# should we build the gui toys?
AM_CONDITIONAL(BUILD_GUI, [test "x$build_webkit" = "xyes" -a "x$have_gio" = "xyes"])
############################################################################### ###############################################################################
@ -344,21 +295,10 @@ echo "Xapian version : $xapian_version"
echo "GLib version : $glib_version" echo "GLib version : $glib_version"
echo "GMime version : $gmime_version" echo "GMime version : $gmime_version"
if test "x$buildgui" = "xyes"; then AM_COND_IF([BUILD_GUI],[
echo "GTK+ version : $gtk_version" echo "GTK+ version : $gtk_version"
fi
if test "x$have_gio" = "xyes"; then
echo "GIO version : $gio_version"
fi
if test "x$build_webkit" = "xyes"; then
echo "Webkit version : $webkit_version" echo "Webkit version : $webkit_version"
fi ])
if test "x$build_guile" = "xyes"; then
echo "Guile version : $guile_version"
fi
if test "x$build_mu4e" = "xyes"; then if test "x$build_mu4e" = "xyes"; then
echo "Emacs version : $emacs_version" echo "Emacs version : $emacs_version"
@ -368,7 +308,11 @@ echo
echo "Have wordexp : $ac_cv_header_wordexp_h" echo "Have wordexp : $ac_cv_header_wordexp_h"
echo "Build mu4e emacs frontend : $build_mu4e" echo "Build mu4e emacs frontend : $build_mu4e"
echo "Build crypto support (gmime >= 2.6) : $have_gmime_26" echo "Build crypto support (gmime >= 2.6) : $have_gmime_26"
echo "Build 'mug' toy-ui (gtk+/webkit) : $buildgui" AM_COND_IF([BUILD_GUI],[
echo "Build 'mug' toy-ui (gtk+/webkit) : yes"],[
echo "Build 'mug' toy-ui (gtk+/webkit) : no"
])
echo "McCabe's Cyclomatic Complexity tool : $have_pmccabe" echo "McCabe's Cyclomatic Complexity tool : $have_pmccabe"
echo echo
@ -395,10 +339,6 @@ if test "x$buildgui" = "xyes"; then
echo echo
fi fi
# the unit tests
echo "* You can run 'make check' to run the unit tests"
echo
# wordexp # wordexp
if test "x$ac_cv_header_wordexp_h" != "xyes"; then if test "x$ac_cv_header_wordexp_h" != "xyes"; then
echo "* Your system does not seem to have the 'wordexp' function." echo "* Your system does not seem to have the 'wordexp' function."
@ -410,5 +350,5 @@ if test "x$ac_cv_header_wordexp_h" != "xyes"; then
fi fi
echo echo
echo "Now, type 'make' to build mu." echo "Now, type 'make' to build mu (or 'make check' to run the unit tests, too)"
echo echo

View File

@ -166,8 +166,9 @@ static const MuMsgField FIELD_DATA[] = {
{ {
MU_MSG_FIELD_ID_MAILING_LIST, MU_MSG_FIELD_ID_MAILING_LIST,
MU_MSG_FIELD_TYPE_STRING, MU_MSG_FIELD_TYPE_STRING,
"list", 'v', 'L', "list", 'v', 'V',
FLAG_GMIME | FLAG_XAPIAN_VALUE FLAG_GMIME | FLAG_XAPIAN_TERM | FLAG_XAPIAN_VALUE |
FLAG_XAPIAN_ESCAPE
}, },

View File

@ -405,7 +405,10 @@ const MuMsgIterThreadInfo*
mu_msg_iter_get_thread_info (MuMsgIter *iter) mu_msg_iter_get_thread_info (MuMsgIter *iter)
{ {
g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL); g_return_val_if_fail (!mu_msg_iter_is_done(iter), NULL);
g_return_val_if_fail (iter->thread_hash(), NULL);
/* maybe we don't have thread info */
if (!iter->thread_hash())
return NULL;
try { try {
const MuMsgIterThreadInfo *ti; const MuMsgIterThreadInfo *ti;

View File

@ -179,6 +179,7 @@ typedef struct _MuMsgIterThreadInfo MuMsgIterThreadInfo;
/** /**
* get a the MuMsgThreaderInfo struct for this message; this only * get a the MuMsgThreaderInfo struct for this message; this only
* works when you created the mu-msg-iter with threading enabled * works when you created the mu-msg-iter with threading enabled
* (otherwise, return NULL)
* *
* @param iter a valid MuMsgIter iterator * @param iter a valid MuMsgIter iterator
* *

View File

@ -1,4 +1,4 @@
.TH MU SCRIPT 1 "October 2012" "User Manuals" .TH MU SCRIPT 1 "March 2013" "User Manuals"
.SH NAME .SH NAME
@ -81,3 +81,4 @@ Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
.SH "SEE ALSO" .SH "SEE ALSO"
.BR mu(1) .BR mu(1)
.BR guile(1)

View File

@ -1,4 +1,4 @@
.TH MU 1 "January 2012" "User Manuals" .TH MU 1 "March 2013" "User Manuals"
.SH NAME .SH NAME
@ -7,19 +7,41 @@ index and search e-mail messages.
.SH SYNOPSIS .SH SYNOPSIS
In alphabetical order:
.B mu [options] .B mu [options]
general mu command
.B mu index [options] .B mu add
add specific messages to the database
.B mu find [options] <search expression>
.B mu view <file> [<files>]
.B mu mkdir [options] <dir> [<dirs>]
.B mu extract [options] <file> [<parts>] [<regexp>]
.B mu cfind [options] [<regexp>] .B mu cfind [options] [<regexp>]
find contacts
.B mu extract [options] <file> [<parts>] [<regexp>]
extract attachments and other MIME-parts
.B mu find [options] <search expression>
find messages
.B mu index [options]
(re)index the messages in a Maildir
.B mu mkdir [options] <dir> [<dirs>]
create a new Maildir
.B mu remove [options]
remove specific messages from the database
.B mu script [options]
run a mu (Guile) script
.B mu server [options]
start a server process (for \fBmu4e\fR-internal use)
.B mu view <file> [<files>]
view a specific message
.SH DESCRIPTION .SH DESCRIPTION
@ -176,34 +198,34 @@ non-zero when some error occured. The table lists the various error codes.
.nf .nf
exit code | error exit code | error
----------+------------------------------------------- ----------+-------------------------------------------
1 | MU_ERROR 1 | MU_ERROR
2 | MU_ERROR_IN_PARAMETERS 2 | MU_ERROR_IN_PARAMETERS
3 | MU_ERROR_INTERNAL 3 | MU_ERROR_INTERNAL
4 | MU_ERROR_NO_MATCHES 4 | MU_ERROR_NO_MATCHES
| |
11 | MU_ERROR_XAPIAN 11 | MU_ERROR_XAPIAN
| |
13 | MU_ERROR_XAPIAN_QUERY 13 | MU_ERROR_XAPIAN_QUERY
14 | MU_ERROR_XAPIAN_DIR_NOT_ACCESSIBLE 14 | MU_ERROR_XAPIAN_DIR_NOT_ACCESSIBLE
15 | MU_ERROR_XAPIAN_NOT_UP_TO_DATE 15 | MU_ERROR_XAPIAN_NOT_UP_TO_DATE
16 | MU_ERROR_XAPIAN_MISSING_DATA 16 | MU_ERROR_XAPIAN_MISSING_DATA
17 | MU_ERROR_XAPIAN_CORRUPTION 17 | MU_ERROR_XAPIAN_CORRUPTION
18 | MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK 18 | MU_ERROR_XAPIAN_CANNOT_GET_WRITELOCK
30 | MU_ERROR_GMIME 30 | MU_ERROR_GMIME
| |
50 | MU_ERROR_CONTACTS 50 | MU_ERROR_CONTACTS
51 | MU_ERROR_CONTACTS_CANNOT_RETRIEVE 51 | MU_ERROR_CONTACTS_CANNOT_RETRIEVE
| |
70 | MU_ERROR_FILE 70 | MU_ERROR_FILE
71 | MU_ERROR_FILE_INVALID_NAME 71 | MU_ERROR_FILE_INVALID_NAME
72 | MU_ERROR_FILE_CANNOT_LINK 72 | MU_ERROR_FILE_CANNOT_LINK
73 | MU_ERROR_FILE_CANNOT_OPEN 73 | MU_ERROR_FILE_CANNOT_OPEN
74 | MU_ERROR_FILE_CANNOT_READ 74 | MU_ERROR_FILE_CANNOT_READ
75 | MU_ERROR_FILE_CANNOT_CREATE 75 | MU_ERROR_FILE_CANNOT_CREATE
76 | MU_ERROR_FILE_CANNOT_MKDIR 76 | MU_ERROR_FILE_CANNOT_MKDIR
77 | MU_ERROR_FILE_STAT_FAILED 77 | MU_ERROR_FILE_STAT_FAILED
78 | MU_ERROR_FILE_READDIR_FAILED 78 | MU_ERROR_FILE_READDIR_FAILED
79 | MU_ERROR_FILE_INVALID_SOURCE 79 | MU_ERROR_FILE_INVALID_SOURCE
.fi .fi
.SH BUGS .SH BUGS

View File

@ -148,7 +148,8 @@ check_params (MuConfig *opts, GError **err)
{ {
if (!mu_util_supports (MU_FEATURE_GUILE | MU_FEATURE_GNUPLOT)) { if (!mu_util_supports (MU_FEATURE_GUILE | MU_FEATURE_GNUPLOT)) {
mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS, mu_util_g_set_error (err, MU_ERROR_IN_PARAMETERS,
"the 'script' command is not supported"); "the 'script' command is not available "
"in this version of mu");
return FALSE; return FALSE;
} }

View File

@ -529,7 +529,7 @@ show_usage (void)
{ {
g_print ("usage: mu command [options] [parameters]\n"); g_print ("usage: mu command [options] [parameters]\n");
g_print ("where command is one of index, find, cfind, view, mkdir, " g_print ("where command is one of index, find, cfind, view, mkdir, "
"extract, add, remove, stats, verify or server\n"); "extract, add, remove, script, verify or server\n");
g_print ("see the mu, mu-<command> or mu-easy manpages for " g_print ("see the mu, mu-<command> or mu-easy manpages for "
"more information\n"); "more information\n");
} }

View File

@ -1,6 +1,6 @@
#-*-mode:org-*- #-*-mode:org-*-
# #
# Copyright (C) 2012 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> # Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -83,7 +83,7 @@ is one of:
index - index messages index - index messages
mkdir - create a maildir mkdir - create a maildir
remove - remove a message from the database remove - remove a message from the database
script - run a script script - run a script (available only when mu was built with guile-support)
server - start mu server server - start mu server
verify - verify signatures of a message verify - verify signatures of a message
view - view a specific message view - view a specific message

View File

@ -187,7 +187,28 @@ store your org-contacts."
Make sure it is one of the headers mu recognizes for storing Make sure it is one of the headers mu recognizes for storing
tags: X-Keywords, X-Label, Keywords. Also note that changing tags: X-Keywords, X-Label, Keywords. Also note that changing
this setting on already tagged messages can lead to messages this setting on already tagged messages can lead to messages
with multiple tags headers") with multiple tags headers.")
(defun mu4e~contains-line-matching (regexp path)
"Determine whether the file at path contains a line matching
the given regexp."
(with-temp-buffer
(insert-file-contents path)
(save-excursion
(goto-char (point-min))
(if (re-search-forward regexp nil t)
t
nil))))
(defun mu4e~replace-first-line-matching (regexp to-string path)
"Replace the first line in the file at path that matches regexp
with the string replace."
(with-temp-file path
(insert-file-contents path)
(save-excursion
(goto-char (point-min))
(if (re-search-forward regexp nil t)
(replace-match to-string nil nil)))))
(defun mu4e-action-retag-message (msg &optional retag-arg) (defun mu4e-action-retag-message (msg &optional retag-arg)
"Change tags of a message. Example: +tag \"+long tag\" -oldtag "Change tags of a message. Example: +tag \"+long tag\" -oldtag
@ -203,28 +224,31 @@ store your org-contacts."
(t ", "))) (t ", ")))
(taglist (if oldtags (copy-sequence oldtags) '())) (taglist (if oldtags (copy-sequence oldtags) '()))
tagstr) tagstr)
(dolist (tag (split-string-and-unquote retag) taglist) (dolist (tag (split-string-and-unquote retag) taglist)
(cond ((string-match "\\+\\(.+\\)" tag) (cond
(setq taglist (push (match-string 1 tag) taglist))) ((string-match "^\\+\\(.+\\)" tag)
((string-match "\\-\\(.+\\)" tag) (setq taglist (push (match-string 1 tag) taglist)))
((string-match "^\\-\\(.+\\)" tag)
(setq taglist (delete (match-string 1 tag) taglist))) (setq taglist (delete (match-string 1 tag) taglist)))
(t (t
(setq taglist (push tag taglist))))) (setq taglist (push tag taglist)))))
(setq taglist (sort (delete-dups taglist) 'string<)) (setq taglist (sort (delete-dups taglist) 'string<))
(setq tagstr (mapconcat 'identity taglist sep)) (setq tagstr (mapconcat 'identity taglist sep))
(setq tagstr (replace-regexp-in-string "[\\/&]" "\\\\\\&" tagstr))
(if (string= (shell-command-to-string (format "sed -n '1,/^$/ {/^%s:/I p}' \"%s\"" (setq tagstr (replace-regexp-in-string "[\\&]" "\\\\\\&" tagstr))
mu4e-action-tags-header path)) "") (setq tagstr (replace-regexp-in-string "[/]" "\\&" tagstr))
;; Add tags header just before the content
(call-process "sed" nil nil nil "-i"
(format "1,/^$/s/^$/%s: %s\\n/I" header tagstr) path)
;; replaces keywords with sed, restricted to the header (if (not (mu4e~contains-line-matching (concat header ":.*") path))
(call-process "sed" nil nil nil "-i" ;; Add tags header just before the content
(format "1,/^$/s/^%s:.*$/%s: %s/I" header header tagstr) path)) (mu4e~replace-first-line-matching
"^$" (concat header ": " tagstr "\n") path)
;; replaces keywords, restricted to the header
(mu4e~replace-first-line-matching
(concat header ":.*")
(concat header ": " tagstr)
path))
(mu4e-message (concat "tagging: " (mapconcat 'identity taglist ", "))) (mu4e-message (concat "tagging: " (mapconcat 'identity taglist ", ")))
(mu4e-refresh-message path maildir))) (mu4e-refresh-message path maildir)))

View File

@ -27,7 +27,7 @@ Documentation License.''
@end copying @end copying
@titlepage @titlepage
@title @t{mu4e} - an e-mail client for emacs @title @t{mu4e} - an e-mail client for Emacs
@subtitle version @value{mu-version} @subtitle version @value{mu-version}
@author Dirk-Jan C. Binnema @author Dirk-Jan C. Binnema
@ -39,7 +39,7 @@ Documentation License.''
@dircategory Emacs @dircategory Emacs
@direntry @direntry
* mu4e: (mu4e). An email client for emacs. * mu4e: (mu4e). An email client for Emacs.
@end direntry @end direntry
@contents @contents
@ -56,12 +56,12 @@ Documentation License.''
Welcome to @t{mu4e}! Welcome to @t{mu4e}!
@t{mu4e} (@t{mu}-for-@command{emacs}) is an e-mail client for GNU-Emacs version 23 @t{mu4e} (@t{mu}-for-emacs) is an e-mail client for GNU-Emacs version 23 and
and later, built on top of the later, built on top of the
@t{mu}@footnote{@url{http://www.djcbsoftware.nl/code/mu}} e-mail search @t{mu}@footnote{@url{http://www.djcbsoftware.nl/code/mu}} e-mail search
engine. @t{mu4e} is optimized for fast handling of large amounts of e-mail. engine. @t{mu4e} is optimized for fast handling of large amounts of e-mail.
Some of its key characteristics include: Some of mu4e's highlights:
@itemize @itemize
@item Fully search-based: there are no folders@footnote{that is, instead of @item Fully search-based: there are no folders@footnote{that is, instead of
@ -71,20 +71,21 @@ queries
@item User-interface optimized for speed, with quick key strokes for common actions @item User-interface optimized for speed, with quick key strokes for common actions
@item Support for non-English languages (so ``angstrom'' will match ``Ångström'') @item Support for non-English languages (so ``angstrom'' will match ``Ångström'')
@item Asynchronous; heavy actions don't block @command{emacs}@footnote{currently, @item Asynchronous; heavy actions don't block @command{emacs}@footnote{currently,
the only exception to this is @emph{sending mail}} the only exception to this is @emph{sending mail}; there are solutions for
that though - see the @ref{FAQ}}
@item Support for crypto @item Support for crypto
@item Writing rich-text e-mails using @t{org-mode} @item Writing rich-text e-mails using @t{org-mode}
@item Address auto-completion based on your messages @item Address auto-completion based on the contacts in your messages
@item Extendable with your own code @item Extendable with your own snippets of elisp
@end itemize @end itemize
In this manual, we go through the installation of @t{mu4e}, do some basic In this manual, we go through the installation of @t{mu4e}, do some basic
configuration and explain its daily use. We also show you how you can configuration and explain its daily use. We also show you how you can
customize @t{mu4e} for your needs. customize @t{mu4e} for your needs.
At the end of the manual, there are some example configurations, to get up to At the end of the manual, there are some example configurations, to get you up
speed quickly - @ref{Example configurations}. There's also a section of to speed quickly: @ref{Example configurations}. There's also an @ref{FAQ},
@ref{FAQ}, which should help you with some common questions. which should help you with some common questions.
@menu @menu
* Introduction:: How it all began * Introduction:: How it all began
@ -176,24 +177,26 @@ efficiently as possible.
If @t{mu4e} looks like something for you, give it a shot! We've been trying If @t{mu4e} looks like something for you, give it a shot! We've been trying
hard to make it as easy as possible to set up and use; and while you can use hard to make it as easy as possible to set up and use; and while you can use
elisp is various places to augment @t{mu4e}, programming is by no mean required. elisp in various places to augment @t{mu4e}, a lot of knowledge about
programming or elisp shouldn't be required.
When you take @t{mu4e} into use, it's a good idea to subscribe to the When you take @t{mu4e} into use, it's a good idea to subscribe to the
@t{mu}/@t{mu4e}-mailing @t{mu}/@t{mu4e}-mailing
list@footnote{@url{http://groups.google.com/group/mu-discuss}}. If you have list@footnote{@url{http://groups.google.com/group/mu-discuss}}.
suggestions for improvements or bug reports, please use the GitHub issues
list@footnote{@url{https://github.com/djcb/mu/issues}}. In bug reports, please If you have suggestions for improvements or bug reports, please use the GitHub
clearly specify the versions of @t{mu}/@t{mu4e} and @command{emacs} you are issues list@footnote{@url{https://github.com/djcb/mu/issues}}. In bug reports,
using, as well as any other relevant details. If you are new to all this, the please clearly specify the versions of @t{mu}/@t{mu4e} and @command{emacs} you
somewhat paternalistic @emph{``How to ask questions the smart are using, as well as any other relevant details. If you are new to all this,
way''}@footnote{@url{http://www.catb.org/esr/faqs/smart-questions.html}} can be the somewhat paternalistic @emph{``How to ask questions the smart
a good read. way''}@footnote{@url{http://www.catb.org/esr/faqs/smart-questions.html}} can
be a good read.
@node Getting started @node Getting started
@chapter Getting started @chapter Getting started
In this chapter, we go through the installation of @t{mu4e} and its basic In this chapter, we go through the installation of @t{mu4e} and its basic
setup. After we have succeeded in @ref{Getting mail}, and @ref{Indexing your setup. After we have succeeded in @ref{Getting mail}, and @pxref{Indexing your
messages}, we discuss @ref{Basic configuration}. messages}, we discuss @ref{Basic configuration}.
After these steps, @t{mu4e} should be ready to go! After these steps, @t{mu4e} should be ready to go!
@ -218,10 +221,16 @@ After these steps, @t{mu4e} should be ready to go!
systems, including many Linux distributions, MacOS and systems, including many Linux distributions, MacOS and
FreeBSD. @command{emacs} 23 or 24 is required, as well as FreeBSD. @command{emacs} 23 or 24 is required, as well as
Xapian@footnote{@url{http://xapian.org/}} and Xapian@footnote{@url{http://xapian.org/}} and
GMime@footnote{@url{http://spruce.sourceforge.net/gmime/}}. If you intend to GMime@footnote{@url{http://spruce.sourceforge.net/gmime/}}.
compile yourself, you need to have the typical development tools, such as C
and C++ compilers (both @command{gcc} and @command{clang} should work) and @t{mu} has optional support the Guile 2.x (Scheme) programming language. There
@command{make}. are also some GUI-tools, which require GTK+ and Webkit; either the GTK+2 or
GTK+3-versions.
If you intend to compile it yourself, you need to have the typical development
tools, such as C and C++ compilers (both @command{gcc} and @command{clang}
should work), GNU Autotools and @command{make}, and (if you use them) the
development packages for GTK+, Webkit and Guile.
@node Installation @node Installation
@section Installation @section Installation
@ -1536,7 +1545,10 @@ date:today..now
# get all messages we got in the last two weeks regarding emacs: # get all messages we got in the last two weeks regarding emacs:
date:2w..now emacs date:2w..now emacs
# get mails with a subject soccer, Socrates, society...: # get messages from the the Mu mailing list:
mu find list:mu-discuss.googlegroups.com
# get messages with a subject soccer, Socrates, society...:
subject:soc* subject:soc*
# note: the '*' wildcard can only appear as the term's rightmost character # note: the '*' wildcard can only appear as the term's rightmost character
@ -1549,7 +1561,8 @@ mime:application/pdf
# get all messages with image attachments: # get all messages with image attachments:
mime:image/* mime:image/*
# note: the '*' wildcard can only appear as the term's rightmost character # note: the '*' wildcard can only appear as the term's @emph{rightmost}
# character
@end verbatim @end verbatim
@node Bookmarks @node Bookmarks
@ -2914,6 +2927,19 @@ messages}.
like Gmail does?} Yes -- see @ref{Including related messages}. like Gmail does?} Yes -- see @ref{Including related messages}.
@item @emph{There seem to be a lot of duplicate messages -- how can I get rid @item @emph{There seem to be a lot of duplicate messages -- how can I get rid
of them?} See @ref{Skipping duplicates}. of them?} See @ref{Skipping duplicates}.
@item @emph{Some messages are almost unreadable in emacs - can I view them in
an external web browser?} Indeed, airlines often send messages that heavily
depend on html and are hard to digest inside emacs. Fortunately, there's an
@emph{action} (@ref{Adding an action in the message view}) defined for
this. Simply add to your configuration:
@lisp
(add-to-list 'mu4e-view-actions
'("ViewInBrowser" . mu4e-action-view-in-browser) t)
@end lisp
Now, when viewing such a difficult message, type @kbd{aV}, and the message
opens inside a webbrowser. You can influence the browser with
@code{browse-url-generic-program}.
@end enumerate @end enumerate
@node Writing messages @node Writing messages
@ -2948,6 +2974,17 @@ messages stay around. How can I get rid of those?}
@lisp @lisp
(setq message-kill-buffer-on-exit t) (setq message-kill-buffer-on-exit t)
@end lisp @end lisp
@item @emph{Sending big messages is slow and blocks emacs - what can I do
about it?} For this, there's @url{https://github.com/jwiegley/emacs-async}
(also available from the Emacs package repository); add the following snippet
to your configuration:
@lisp
(require 'smtpmail-async)
(setq
send-mail-function 'async-smtpmail-send-it
message-send-mail-function 'async-smtpmail-send-it)
@end lisp
With this, messages are sent using background emacs-instance.
@end enumerate @end enumerate
@node Known issues @node Known issues

View File

@ -1,5 +1,5 @@
/* /*
** Copyright (C) 2011-2012 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2011-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify it ** 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 ** under the terms of the GNU General Public License as published by the
@ -252,8 +252,8 @@ each_part (MuMsg *msg, MuMsgPart *part, CBData *cbdata)
pixbuf = mu_widget_util_get_icon_pixbuf_for_content_type (ctype, 16); pixbuf = mu_widget_util_get_icon_pixbuf_for_content_type (ctype, 16);
if (!pixbuf) { if (!pixbuf) {
g_warning ("%s: could not get icon pixbuf for '%s'", g_debug ("%s: could not get icon pixbuf for '%s'",
__FUNCTION__, ctype); __FUNCTION__, ctype);
pixbuf = mu_widget_util_get_icon_pixbuf_for_content_type pixbuf = mu_widget_util_get_icon_pixbuf_for_content_type
("application/octet-stream", 16); ("application/octet-stream", 16);
} }

View File

@ -39,27 +39,18 @@ enum {
}; };
struct _MuMsgHeaderViewPrivate { struct _MuMsgHeaderViewPrivate {
GtkWidget *_table; GtkWidget *_grid;
}; };
#define MU_MSG_HEADER_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ #define MU_MSG_HEADER_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
MU_TYPE_MSG_HEADER_VIEW, \ MU_TYPE_MSG_HEADER_VIEW, \
MuMsgHeaderViewPrivate)) MuMsgHeaderViewPrivate))
/* globals */ /* globals */
#ifdef HAVE_GTK3
static GtkBoxClass *parent_class = NULL; static GtkBoxClass *parent_class = NULL;
#else
static GtkVBoxClass *parent_class = NULL;
#endif /*!HAVE_GTK3*/
/* uncomment the following if you have defined any signals */ /* uncomment the following if you have defined any signals */
/* static guint signals[LAST_SIGNAL] = {0}; */ /* static guint signals[LAST_SIGNAL] = {0}; */
#ifdef HAVE_GTK3
G_DEFINE_TYPE (MuMsgHeaderView, mu_msg_header_view, GTK_TYPE_BOX); G_DEFINE_TYPE (MuMsgHeaderView, mu_msg_header_view, GTK_TYPE_BOX);
#else
G_DEFINE_TYPE (MuMsgHeaderView, mu_msg_header_view, GTK_TYPE_VBOX);
#endif /*!HAVE_GTK3*/
static void static void
@ -85,13 +76,9 @@ static void
mu_msg_header_view_init (MuMsgHeaderView *obj) mu_msg_header_view_init (MuMsgHeaderView *obj)
{ {
/* #ifdef HAVE_GTK3 */
/* static GtkBoxClass *parent_class = NULL; */ /* static GtkBoxClass *parent_class = NULL; */
/* #endif /\*!HAVE_GTK3*\/ */
obj->_priv = MU_MSG_HEADER_VIEW_GET_PRIVATE(obj); obj->_priv = MU_MSG_HEADER_VIEW_GET_PRIVATE(obj);
obj->_priv->_table = NULL; obj->_priv->_grid = NULL;
} }
static void static void
@ -129,7 +116,7 @@ get_label (const gchar *txt, gboolean istitle)
} }
static gboolean static gboolean
add_row (GtkWidget *table, guint row, const char* fieldname, const char *value, add_row (GtkWidget *grid, guint row, const char* fieldname, const char *value,
gboolean showempty) gboolean showempty)
{ {
GtkWidget *label, *al; GtkWidget *label, *al;
@ -137,52 +124,49 @@ add_row (GtkWidget *table, guint row, const char* fieldname, const char *value,
if (!value && !showempty) if (!value && !showempty)
return FALSE; return FALSE;
gtk_grid_insert_row (GTK_GRID(grid), row);
label = get_label (fieldname, TRUE); label = get_label (fieldname, TRUE);
al = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); al = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
gtk_container_add (GTK_CONTAINER (al), label); gtk_container_add (GTK_CONTAINER (al), label);
gtk_table_attach ( gtk_grid_attach (GTK_GRID(grid), al, 0, row, 1, 1);
GTK_TABLE(table), al,
0, 1, row, row + 1, GTK_FILL, 0, 0, 0);
al = gtk_alignment_new (0.0, 1.0, 0.0, 0.0); al = gtk_alignment_new (0.0, 1.0, 0.0, 0.0);
label = get_label (value, FALSE); label = get_label (value, FALSE);
gtk_container_add (GTK_CONTAINER (al), label); gtk_container_add (GTK_CONTAINER (al), label);
gtk_grid_attach (GTK_GRID(grid), al, 1, row, 1, 1);
gtk_table_attach (
GTK_TABLE(table), al, 1, 2, row, row + 1, GTK_FILL,
0, 0, 0);
return TRUE; return TRUE;
} }
GtkWidget * GtkWidget *
get_table (MuMsg *msg) get_grid (MuMsg *msg)
{ {
GtkWidget *table; GtkWidget *grid;
int row; int row;
row = 0; row = 0;
grid = gtk_grid_new (); /* 5 2 */
table = gtk_table_new (5, 2, FALSE); gtk_grid_insert_column (GTK_GRID(grid), 0);
gtk_grid_insert_column (GTK_GRID(grid), 1);
if (add_row (table, row, "From", mu_msg_get_from (msg), TRUE)) if (add_row (grid, row, "From", mu_msg_get_from (msg), TRUE))
++row; ++row;
if (add_row (table, row, "To", mu_msg_get_to (msg), FALSE)) if (add_row (grid, row, "To", mu_msg_get_to (msg), FALSE))
++row; ++row;
if (add_row (table, row, "Cc", mu_msg_get_cc (msg), FALSE)) if (add_row (grid, row, "Cc", mu_msg_get_cc (msg), FALSE))
++row; ++row;
if (add_row (table, row, "Subject", mu_msg_get_subject (msg), TRUE)) if (add_row (grid, row, "Subject", mu_msg_get_subject (msg), TRUE))
++row; ++row;
if (add_row (table, row, "Date", mu_date_str_s if (add_row (grid, row, "Date", mu_date_str_s
("%c", mu_msg_get_date (msg)),TRUE)) ("%c", mu_msg_get_date (msg)),TRUE))
++row; ++row;
gtk_table_resize (GTK_TABLE(table), row, 2); return grid;
return table;
} }
void void
@ -190,15 +174,15 @@ mu_msg_header_view_set_message (MuMsgHeaderView *self, MuMsg *msg)
{ {
g_return_if_fail (MU_IS_MSG_HEADER_VIEW(self)); g_return_if_fail (MU_IS_MSG_HEADER_VIEW(self));
if (self->_priv->_table) { if (self->_priv->_grid) {
gtk_container_remove (GTK_CONTAINER(self), self->_priv->_table); gtk_container_remove (GTK_CONTAINER(self), self->_priv->_grid);
self->_priv->_table = NULL; self->_priv->_grid = NULL;
} }
if (msg) { if (msg) {
self->_priv->_table = get_table (msg); self->_priv->_grid = get_grid (msg);
gtk_box_pack_start (GTK_BOX(self), self->_priv->_table, gtk_box_pack_start (GTK_BOX(self), self->_priv->_grid,
TRUE, TRUE, 0); TRUE, TRUE, 0);
gtk_widget_show_all (self->_priv->_table); gtk_widget_show_all (self->_priv->_grid);
} }
} }

View File

@ -42,24 +42,14 @@ typedef struct _MuMsgHeaderViewClass MuMsgHeaderViewClass;
typedef struct _MuMsgHeaderViewPrivate MuMsgHeaderViewPrivate; typedef struct _MuMsgHeaderViewPrivate MuMsgHeaderViewPrivate;
struct _MuMsgHeaderView { struct _MuMsgHeaderView {
#ifdef HAVE_GTK3
GtkBox parent; GtkBox parent;
#else
GtkVBox parent;
#endif /*!HAVE_GTK3*/
/* insert public members, if any */ /* insert public members, if any */
/* private */ /* private */
MuMsgHeaderViewPrivate *_priv; MuMsgHeaderViewPrivate *_priv;
}; };
struct _MuMsgHeaderViewClass { struct _MuMsgHeaderViewClass {
#ifdef HAVE_GTK3
GtkBoxClass parent_class; GtkBoxClass parent_class;
#else
GtkVBoxClass parent_class;
#endif /*!HAVE_GTK3*/
/* insert signal callback declarations, e.g. */ /* insert signal callback declarations, e.g. */
/* void (* my_event) (MuMsgHeaderView* obj); */ /* void (* my_event) (MuMsgHeaderView* obj); */
}; };

View File

@ -48,24 +48,12 @@ struct _MuMsgViewPrivate {
MU_TYPE_MSG_VIEW, \ MU_TYPE_MSG_VIEW, \
MuMsgViewPrivate)) MuMsgViewPrivate))
/* globals */ /* globals */
#ifdef HAVE_GTK3
static GtkBoxClass *parent_class = NULL; static GtkBoxClass *parent_class = NULL;
#else
static GtkVBoxClass *parent_class = NULL;
#endif /*!HAVE_GTK3*/
/* uncomment the following if you have defined any signals */ /* uncomment the following if you have defined any signals */
/* static guint signals[LAST_SIGNAL] = {0}; */ /* static guint signals[LAST_SIGNAL] = {0}; */
#ifdef HAVE_GTK3
G_DEFINE_TYPE (MuMsgView, mu_msg_view, GTK_TYPE_BOX); G_DEFINE_TYPE (MuMsgView, mu_msg_view, GTK_TYPE_BOX);
#else
G_DEFINE_TYPE (MuMsgView, mu_msg_view, GTK_TYPE_VBOX);
#endif /*HAVE_GTK3*/
static void static void
set_message (MuMsgView *self, MuMsg *msg) set_message (MuMsgView *self, MuMsg *msg)
@ -154,11 +142,12 @@ on_attach_activated (GtkWidget *w, guint partnum, MuMsg *msg)
static void static void
mu_msg_view_init (MuMsgView *self) mu_msg_view_init (MuMsgView *self)
{ {
self->_priv = MU_MSG_VIEW_GET_PRIVATE(self); gtk_orientable_set_orientation (GTK_ORIENTABLE(self),
GTK_ORIENTATION_VERTICAL);
self->_priv = MU_MSG_VIEW_GET_PRIVATE(self);
self->_priv->_msg = NULL; self->_priv->_msg = NULL;
self->_priv->_headers = mu_msg_header_view_new (); self->_priv->_headers = mu_msg_header_view_new ();
self->_priv->_attach = mu_msg_attach_view_new (); self->_priv->_attach = mu_msg_attach_view_new ();
self->_priv->_attachexpander = gtk_expander_new_with_mnemonic self->_priv->_attachexpander = gtk_expander_new_with_mnemonic
("_Attachments"); ("_Attachments");
@ -178,6 +167,10 @@ mu_msg_view_init (MuMsgView *self)
FALSE, FALSE, 2); FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX(self), self->_priv->_attachexpander, gtk_box_pack_start (GTK_BOX(self), self->_priv->_attachexpander,
FALSE, FALSE, 2); FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX(self),
gtk_separator_new(GTK_ORIENTATION_HORIZONTAL),
TRUE,TRUE,0);
gtk_box_pack_start (GTK_BOX(self), self->_priv->_body, gtk_box_pack_start (GTK_BOX(self), self->_priv->_body,
TRUE, TRUE, 2); TRUE, TRUE, 2);
} }

View File

@ -42,22 +42,13 @@ typedef struct _MuMsgViewClass MuMsgViewClass;
typedef struct _MuMsgViewPrivate MuMsgViewPrivate; typedef struct _MuMsgViewPrivate MuMsgViewPrivate;
struct _MuMsgView { struct _MuMsgView {
#ifdef HAVE_GTK3
GtkBox parent; GtkBox parent;
#else
GtkVBox parent;
#endif /*!HAVE_GTK3*/
/* private */ /* private */
MuMsgViewPrivate *_priv; MuMsgViewPrivate *_priv;
}; };
struct _MuMsgViewClass { struct _MuMsgViewClass {
#ifdef HAVE_GTK3
GtkBoxClass parent_class; GtkBoxClass parent_class;
#else
GtkVBoxClass parent_class;
#endif /*!HAVE_GTK3*/
/* void (* my_event) (MuMsgView* obj); */ /* void (* my_event) (MuMsgView* obj); */
}; };

View File

@ -46,13 +46,8 @@ struct _MugMsgViewPrivate {
#define MUG_MSG_VIEW_GET_PRIVATE(o)(G_TYPE_INSTANCE_GET_PRIVATE((o),MUG_TYPE_MSG_VIEW, MugMsgViewPrivate)) #define MUG_MSG_VIEW_GET_PRIVATE(o)(G_TYPE_INSTANCE_GET_PRIVATE((o),MUG_TYPE_MSG_VIEW, MugMsgViewPrivate))
/* globals */ /* globals */
#ifdef HAVE_GTK3
static GtkBoxClass *parent_class = NULL; static GtkBoxClass *parent_class = NULL;
G_DEFINE_TYPE (MugMsgView, mug_msg_view, GTK_TYPE_BOX); G_DEFINE_TYPE (MugMsgView, mug_msg_view, GTK_TYPE_BOX);
#else
static GtkVBoxClass *parent_class = NULL;
G_DEFINE_TYPE (MugMsgView, mug_msg_view, GTK_TYPE_VBOX);
#endif /*!HAVE_GTK3*/
/* uncomment the following if you have defined any signals */ /* uncomment the following if you have defined any signals */
/* static guint signals[LAST_SIGNAL] = {0}; */ /* static guint signals[LAST_SIGNAL] = {0}; */

View File

@ -1,5 +1,5 @@
/* /*
** Copyright (C) 2010 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2010-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify it ** 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 ** under the terms of the GNU General Public License as published by the
@ -23,9 +23,6 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
/* other include files */ /* other include files */
G_BEGIN_DECLS G_BEGIN_DECLS
/* convenience macros */ /* convenience macros */
#define MUG_TYPE_MSG_VIEW (mug_msg_view_get_type()) #define MUG_TYPE_MSG_VIEW (mug_msg_view_get_type())
@ -38,20 +35,11 @@ typedef struct _MugMsgView MugMsgView;
typedef struct _MugMsgViewClass MugMsgViewClass; typedef struct _MugMsgViewClass MugMsgViewClass;
struct _MugMsgView { struct _MugMsgView {
#ifdef HAVE_GTK3
GtkBox parent; GtkBox parent;
#else
GtkVBox parent;
#endif /*!HAVE_GTK3*/
}; };
struct _MugMsgViewClass { struct _MugMsgViewClass {
#ifdef HAVE_GTK3
GtkBoxClass parent_class; GtkBoxClass parent_class;
#else
GtkVBoxClass parent_class;
#endif /*!HAVE_GTK3*/
/* insert signal callback declarations, e.g. */ /* insert signal callback declarations, e.g. */
/* void (* my_event) (MugMsg* obj); */ /* void (* my_event) (MugMsg* obj); */
}; };
@ -66,4 +54,5 @@ gboolean mug_msg_view_set_msg (MugMsgView * self, const char *msgpath);
void mug_msg_view_set_note (MugMsgView * self, const char* html); void mug_msg_view_set_note (MugMsgView * self, const char* html);
G_END_DECLS G_END_DECLS
#endif /* __MUG_MSG_VIEW_H__ */
#endif /* __MUG_MSG_VIEW_H__ */

View File

@ -29,13 +29,7 @@ static GtkContainerClass *parent_class = NULL;
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
#ifdef HAVE_GTK3
G_DEFINE_TYPE (MugQueryBar, mug_query_bar, GTK_TYPE_BOX); G_DEFINE_TYPE (MugQueryBar, mug_query_bar, GTK_TYPE_BOX);
#else
G_DEFINE_TYPE (MugQueryBar, mug_query_bar, GTK_TYPE_HBOX);
#endif /*!HAVE_GTK3*/
static void static void
mug_query_bar_class_init (MugQueryBarClass * klass) mug_query_bar_class_init (MugQueryBarClass * klass)

View File

@ -22,22 +22,12 @@ typedef struct _MugQueryBar MugQueryBar;
typedef struct _MugQueryBarClass MugQueryBarClass; typedef struct _MugQueryBarClass MugQueryBarClass;
struct _MugQueryBar { struct _MugQueryBar {
#ifdef HAVE_GTK3
GtkBox parent; GtkBox parent;
#else
GtkHBox parent;
#endif /*!HAVE_GTK3*/
}; };
struct _MugQueryBarClass { struct _MugQueryBarClass {
#ifdef HAVE_GTK3
GtkBox parent; GtkBox parent;
GtkBoxClass parent_class; GtkBoxClass parent_class;
#else
GtkHBox parent;
GtkHBoxClass parent_class;
#endif /*!HAVE_GTK3*/
/* insert signal callback declarations, e.g. */ /* insert signal callback declarations, e.g. */
void (*query_changed) (MugQueryBar * obj, const char *query); void (*query_changed) (MugQueryBar * obj, const char *query);
}; };

View File

@ -49,13 +49,8 @@ struct _MugShortcutsPrivate {
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
#ifdef HAVE_GTK3
static GtkBoxClass *parent_class = NULL; static GtkBoxClass *parent_class = NULL;
G_DEFINE_TYPE (MugShortcuts, mug_shortcuts, GTK_TYPE_BOX); G_DEFINE_TYPE (MugShortcuts, mug_shortcuts, GTK_TYPE_BOX);
#else
static GtkVBoxClass *parent_class = NULL;
G_DEFINE_TYPE (MugShortcuts, mug_shortcuts, GTK_TYPE_VBOX);
#endif /*!HAVE_GTK3*/
static void static void
mug_shortcuts_class_init (MugShortcutsClass * klass) mug_shortcuts_class_init (MugShortcutsClass * klass)
@ -87,12 +82,7 @@ static void
mug_shortcuts_init (MugShortcuts * obj) mug_shortcuts_init (MugShortcuts * obj)
{ {
obj->_priv = MUG_SHORTCUTS_GET_PRIVATE (obj); obj->_priv = MUG_SHORTCUTS_GET_PRIVATE (obj);
#ifdef HAVE_GTK3
obj->_priv->_bbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL); obj->_priv->_bbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
#else
obj->_priv->_bbox = gtk_vbutton_box_new ();
#endif /*!HAVE_GTK3*/
gtk_button_box_set_layout (GTK_BUTTON_BOX (obj->_priv->_bbox), gtk_button_box_set_layout (GTK_BUTTON_BOX (obj->_priv->_bbox),
GTK_BUTTONBOX_START); GTK_BUTTONBOX_START);

View File

@ -41,30 +41,18 @@ typedef struct _MugShortcutsClass MugShortcutsClass;
typedef struct _MugShortcutsPrivate MugShortcutsPrivate; typedef struct _MugShortcutsPrivate MugShortcutsPrivate;
struct _MugShortcuts { struct _MugShortcuts {
#ifdef HAVE_GTK3
GtkBox parent; GtkBox parent;
#else
GtkVBox parent;
#endif /*!HAVE_GTK3*/
/* private */ /* private */
MugShortcutsPrivate *_priv; MugShortcutsPrivate *_priv;
}; };
struct _MugShortcutsClass { struct _MugShortcutsClass {
#ifdef HAVE_GTK3
GtkBoxClass parent_class; GtkBoxClass parent_class;
#else
GtkVBoxClass parent_class;
#endif /*!HAVE_GTK3*/
void (*clicked) (MugShortcuts * obj, const char *query); void (*clicked) (MugShortcuts * obj, const char *query);
}; };
/* member functions */ /* member functions */
GType GType mug_shortcuts_get_type (void) G_GNUC_CONST;
mug_shortcuts_get_type (void)
G_GNUC_CONST;
/* parameter-less _new function (constructor) */ /* parameter-less _new function (constructor) */
/* if this is a kind of GtkWidget, it should probably return at GtkWidget* */ /* if this is a kind of GtkWidget, it should probably return at GtkWidget* */
@ -76,4 +64,5 @@ mug_shortcuts_new (const char *bmpath);
/* gboolean mug_shortcuts_has_foo (MugShortcuts *self, gint value); */ /* gboolean mug_shortcuts_has_foo (MugShortcuts *self, gint value); */
G_END_DECLS G_END_DECLS
#endif /* __MUG_SHORTCUTS_H__ */
#endif /* __MUG_SHORTCUTS_H__ */

View File

@ -263,14 +263,8 @@ mug_query_area (MugData * mugdata)
{ {
GtkWidget *queryarea, *paned, *scrolled; GtkWidget *queryarea, *paned, *scrolled;
#ifdef HAVE_GTK3
queryarea = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); queryarea = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL); paned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
#else
queryarea = gtk_vbox_new (FALSE, 2);
paned = gtk_vpaned_new ();
#endif /*!HAVE_GTK3*/
mugdata->mlist = mug_msg_list_view_new mugdata->mlist = mug_msg_list_view_new
(mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB)); (mu_runtime_path(MU_RUNTIME_PATH_XAPIANDB));
@ -310,11 +304,7 @@ mug_main_area (MugData * mugdata)
{ {
GtkWidget *mainarea, *w; GtkWidget *mainarea, *w;
#ifdef HAVE_GTK3
mainarea = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); mainarea = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
#else
mainarea = gtk_hbox_new (FALSE, 5);
#endif /*!HAVE_GTK3*/
w = mug_shortcuts_bar (mugdata); w = mug_shortcuts_bar (mugdata);
gtk_box_pack_start (GTK_BOX (mainarea), w, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (mainarea), w, FALSE, FALSE, 0);
@ -335,11 +325,7 @@ mug_shell (MugData * mugdata)
mugdata->win = gtk_window_new (GTK_WINDOW_TOPLEVEL); mugdata->win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (mugdata->win), "Mug Mail Search"); gtk_window_set_title (GTK_WINDOW (mugdata->win), "Mug Mail Search");
#ifdef HAVE_GTK3
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
#else
vbox = gtk_vbox_new (FALSE, 2);
#endif /*!HAVE_GTK3*/
mugdata->toolbar = mug_toolbar (mugdata); mugdata->toolbar = mug_toolbar (mugdata);
gtk_box_pack_start (GTK_BOX (vbox), mugdata->toolbar, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (vbox), mugdata->toolbar, FALSE, FALSE, 2);
@ -370,11 +356,6 @@ mug_shell (MugData * mugdata)
static gint static gint
on_focus_query_bar (GtkWidget* ignored, GdkEventKey *event, MugData* mugdata) on_focus_query_bar (GtkWidget* ignored, GdkEventKey *event, MugData* mugdata)
{ {
/* gtk2: GDK_Escape; gtk3: GDK_Key_Escape */
#ifndef GDK_KEY_Escape
#define GDK_KEY_Escape GDK_Escape
#endif /* GDK_KEY_Escape */
if (event->type==GDK_KEY_RELEASE && event->keyval==GDK_KEY_Escape) { if (event->type==GDK_KEY_RELEASE && event->keyval==GDK_KEY_Escape) {
mug_query_bar_grab_focus (MUG_QUERY_BAR (mugdata->querybar)); mug_query_bar_grab_focus (MUG_QUERY_BAR (mugdata->querybar));
return 1; return 1;