diff --git a/doc/functions.xml b/doc/functions.xml
index 73b178b061f..908e9571ed6 100644
--- a/doc/functions.xml
+++ b/doc/functions.xml
@@ -89,27 +89,27 @@ in ...
<pkg>.overrideDerivation
- Do not use this function in Nixpkgs. Because it breaks
- package abstraction and doesn’t provide error checking for
- function arguments, it is only intended for ad-hoc customisation
- (such as in ~/.nixpkgs/config.nix).
-
-
-
- Additionally, overrideDerivation forces an evaluation
- of the Derivation which can be quite a performance penalty if there are many
- overrides used.
+ Do not use this function in Nixpkgs as it evaluates a Derivation
+ before modifying it, which breaks package abstraction and removes
+ error-checking of function arguments. In addition, this
+ evaluation-per-function application incurs a performance penalty,
+ which can become a problem if many overrides are used.
+ It is only intended for ad-hoc customisation, such as in
+ ~/.nixpkgs/config.nix.
- The function overrideDerivation is usually available for all the
- derivations in the nixpkgs expression (pkgs).
+ The function overrideDerivation creates a new derivation
+ based on an existing one by overriding the original's attributes with
+ the attribute set produced by the specified function.
+ This function is available on all
+ derivations defined using the makeOverridable function.
+ Most standard derivation-producing functions, such as
+ stdenv.mkDerivation, are defined using this
+ function, which means most packages in the nixpkgs expression,
+ pkgs, have this function.
-
- It is used to create a new derivation by overriding the attributes of
- the original derivation according to the given function.
-
Example usage:
@@ -125,9 +125,9 @@ in ...
- In the above example, the name, src and patches of the derivation
- will be overridden, while all other attributes will be retained from the
- original derivation.
+ In the above example, the name, src,
+ and patches of the derivation will be overridden, while
+ all other attributes will be retained from the original derivation.
@@ -135,6 +135,20 @@ in ...
the original derivation.
+
+
+ A package's attributes are evaluated *before* being modified by
+ the overrideDerivation function.
+ For example, the name attribute reference
+ in url = "mirror://gnu/hello/${name}.tar.gz";
+ is filled-in *before* the overrideDerivation function
+ modifies the attribute set. This means that overriding the
+ name attribute, in this example, *will not* change the
+ value of the url attribute. Instead, we need to override
+ both the name *and* url attributes.
+
+
+
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index 636cb257d6b..f47e481c58a 100644
--- a/lib/attrsets.nix
+++ b/lib/attrsets.nix
@@ -457,7 +457,6 @@ rec {
/*** deprecated stuff ***/
- deepSeqAttrs = throw "removed 2016-02-29 because unused and broken";
zipWithNames = zipAttrsWithNames;
zip = builtins.trace
"lib.zip is deprecated, use lib.zipAttrsWith instead" zipAttrsWith;
diff --git a/lib/lists.nix b/lib/lists.nix
index c810c8c2f5f..6712e5cc93f 100644
--- a/lib/lists.nix
+++ b/lib/lists.nix
@@ -374,8 +374,4 @@ rec {
*/
subtractLists = e: filter (x: !(elem x e));
- /*** deprecated stuff ***/
-
- deepSeqList = throw "removed 2016-02-29 because unused and broken";
-
}
diff --git a/lib/maintainers.nix b/lib/maintainers.nix
index ca4dd4f98e8..3d83a0a3a1c 100644
--- a/lib/maintainers.nix
+++ b/lib/maintainers.nix
@@ -15,6 +15,7 @@
adev = "Adrien Devresse ";
Adjective-Object = "Maxwell Huang-Hobbs ";
adnelson = "Allen Nelson ";
+ adolfogc = "Adolfo E. García Castro ";
aespinosa = "Allan Espinosa ";
aflatter = "Alexander Flatter ";
aforemny = "Alexander Foremny ";
@@ -185,6 +186,7 @@
joamaki = "Jussi Maki ";
joelmo = "Joel Moberg ";
joelteon = "Joel Taylor ";
+ joko = "Ioannis Koutras ";
jpbernardy = "Jean-Philippe Bernardy ";
jraygauthier = "Raymond Gauthier ";
juliendehos = "Julien Dehos ";
@@ -231,6 +233,7 @@
markus1189 = "Markus Hauck ";
markWot = "Markus Wotringer ";
martijnvermaat = "Martijn Vermaat ";
+ martingms = "Martin Gammelsæter ";
matejc = "Matej Cotman ";
mathnerd314 = "Mathnerd314 ";
matthiasbeyer = "Matthias Beyer ";
@@ -420,6 +423,7 @@
wscott = "Wayne Scott ";
wyvie = "Elijah Rum ";
yarr = "Dmitry V. ";
+ yurrriq = "Eric Bailey ";
z77z = "Marco Maggesi ";
zagy = "Christian Zagrodnick ";
zef = "Zef Hemel ";
diff --git a/maintainers/scripts/generate-kde-frameworks.sh b/maintainers/scripts/generate-kde-frameworks.sh
index aa693ced704..e690662b3f2 100755
--- a/maintainers/scripts/generate-kde-frameworks.sh
+++ b/maintainers/scripts/generate-kde-frameworks.sh
@@ -1,3 +1,3 @@
#!/bin/sh
-./fetch-kde-qt.sh http://download.kde.org/stable/frameworks/5.22/ -A '*.tar.xz'
+./fetch-kde-qt.sh http://download.kde.org/stable/frameworks/5.24/ -A '*.tar.xz'
diff --git a/maintainers/scripts/generate-kde-plasma.sh b/maintainers/scripts/generate-kde-plasma.sh
index fa804758f09..ad916f3a25b 100755
--- a/maintainers/scripts/generate-kde-plasma.sh
+++ b/maintainers/scripts/generate-kde-plasma.sh
@@ -1,3 +1,3 @@
#!/bin/sh
-./fetch-kde-qt.sh http://download.kde.org/stable/plasma/5.6.5/ -A '*.tar.xz'
+./fetch-kde-qt.sh http://download.kde.org/stable/plasma/5.7.0/ -A '*.tar.xz'
diff --git a/nixos/doc/manual/man-nixos-version.xml b/nixos/doc/manual/man-nixos-version.xml
new file mode 100644
index 00000000000..db7440977c9
--- /dev/null
+++ b/nixos/doc/manual/man-nixos-version.xml
@@ -0,0 +1,102 @@
+
+
+
+ nixos-version
+ 8
+ NixOS
+
+
+
+ nixos-version
+ show the version of nixpkgs NixOS was built from
+
+
+
+
+ nixos-version
+
+
+
+
+
+Description
+
+This command describes the version of nixpkgs used to build
+NixOS.
+
+By default the output includes:
+
+
+ The NixOS release
+ Number of commits since the release
+ Git SHA of the released commit
+ Codename of the NixOS release
+
+
+
+Example
+
+Here is an example output, and corresponding information:
+$ nixos-version
+16.03.1011.6317da4 (Emu)
+
+
+
+
+
+
+
+ Attribute
+ Value
+
+
+
+
+ NixOS Release
+ 16.03
+
+
+ Commit Count
+ 1011
+
+
+ Commit SHA
+ 6317da4
+
+
+ Release Codename
+ Emu
+
+
+
+
+
+
+
+
+
+
+
+Options
+
+This command accepts the following options:
+
+
+
+
+
+
+
+ The output will be the full hash of the git commit
+$ nixos-version --hash
+6317da40006f6bc2480c6781999c52d88dde2acf
+
+
+
+
+
+
+
+
diff --git a/nixos/doc/manual/man-pages.xml b/nixos/doc/manual/man-pages.xml
index 97a2c16d406..e945e0e6263 100644
--- a/nixos/doc/manual/man-pages.xml
+++ b/nixos/doc/manual/man-pages.xml
@@ -27,5 +27,6 @@
+
diff --git a/nixos/maintainers/scripts/ec2/create-amis.sh b/nixos/maintainers/scripts/ec2/create-amis.sh
index 192f608e138..e26caa19164 100755
--- a/nixos/maintainers/scripts/ec2/create-amis.sh
+++ b/nixos/maintainers/scripts/ec2/create-amis.sh
@@ -13,8 +13,11 @@ echo "NixOS version is $version ($major)"
rm -f ec2-amis.nix
+types="hvm pv"
+stores="ebs s3"
+regions="eu-west-1 eu-central-1 us-east-1 us-west-1 us-west-2 ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2 sa-east-1 ap-south-1"
-for type in hvm pv; do
+for type in $types; do
link=$stateDir/$type
imageFile=$link/nixos.qcow2
system=x86_64-linux
@@ -31,7 +34,7 @@ for type in hvm pv; do
--arg configuration "{ imports = [ ]; ec2.hvm = $hvmFlag; }"
fi
- for store in ebs s3; do
+ for store in $stores; do
bucket=nixos-amis
bucketDir="$version-$type-$store"
@@ -39,7 +42,7 @@ for type in hvm pv; do
prevAmi=
prevRegion=
- for region in eu-west-1 eu-central-1 us-east-1 us-west-1 us-west-2 ap-southeast-1 ap-southeast-2 ap-northeast-1 sa-east-1; do
+ for region in $regions; do
name=nixos-$version-$arch-$type-$store
description="NixOS $system $version ($type-$store)"
@@ -51,10 +54,11 @@ for type in hvm pv; do
echo "doing $name in $region..."
if [ -n "$prevAmi" ]; then
- ami=$(ec2-copy-image \
+ ami=$(aws ec2 copy-image \
--region "$region" \
- --source-region "$prevRegion" --source-ami-id "$prevAmi" \
- --name "$name" --description "$description" | cut -f 2)
+ --source-region "$prevRegion" --source-image-id "$prevAmi" \
+ --name "$name" --description "$description" | json -q .ImageId)
+ if [ "$ami" = null ]; then break; fi
else
if [ $store = s3 ]; then
@@ -85,12 +89,12 @@ for type in hvm pv; do
ec2-upload-bundle \
-m $imageDir/$type.raw.manifest.xml \
-b "$bucket/$bucketDir" \
- -a "$EC2_ACCESS_KEY" -s "$EC2_SECRET_KEY" \
+ -a "$AWS_ACCESS_KEY_ID" -s "$AWS_SECRET_ACCESS_KEY" \
--location EU
touch $imageDir/uploaded
fi
- extraFlags="$bucket/$bucketDir/$type.raw.manifest.xml"
+ extraFlags="--image-location $bucket/$bucketDir/$type.raw.manifest.xml"
else
@@ -115,7 +119,8 @@ for type in hvm pv; do
if [ -z "$snapId" -a -z "$volId" -a -z "$taskId" ]; then
echo "importing $vhdFile..."
taskId=$(ec2-import-volume $vhdFile --no-upload -f vhd \
- -o "$EC2_ACCESS_KEY" -w "$EC2_SECRET_KEY" \
+ -O "$AWS_ACCESS_KEY_ID" -W "$AWS_SECRET_ACCESS_KEY" \
+ -o "$AWS_ACCESS_KEY_ID" -w "$AWS_SECRET_ACCESS_KEY" \
--region "$region" -z "${region}a" \
--bucket "$bucket" --prefix "$bucketDir/" \
| tee /dev/stderr \
@@ -125,15 +130,16 @@ for type in hvm pv; do
if [ -z "$snapId" -a -z "$volId" ]; then
ec2-resume-import $vhdFile -t "$taskId" --region "$region" \
- -o "$EC2_ACCESS_KEY" -w "$EC2_SECRET_KEY"
+ -O "$AWS_ACCESS_KEY_ID" -W "$AWS_SECRET_ACCESS_KEY" \
+ -o "$AWS_ACCESS_KEY_ID" -w "$AWS_SECRET_ACCESS_KEY"
fi
# Wait for the volume creation to finish.
if [ -z "$snapId" -a -z "$volId" ]; then
echo "waiting for import to finish..."
while true; do
- volId=$(ec2-describe-conversion-tasks "$taskId" --region "$region" | sed 's/.*VolumeId.*\(vol-[0-9a-f]\+\).*/\1/ ; t ; d')
- if [ -n "$volId" ]; then break; fi
+ volId=$(aws ec2 describe-conversion-tasks --conversion-task-ids "$taskId" --region "$region" | jq -r .ConversionTasks[0].ImportVolume.Volume.Id)
+ if [ "$volId" != null ]; then break; fi
sleep 10
done
@@ -143,22 +149,24 @@ for type in hvm pv; do
# Delete the import task.
if [ -n "$volId" -a -n "$taskId" ]; then
echo "removing import task..."
- ec2-delete-disk-image -t "$taskId" --region "$region" -o "$EC2_ACCESS_KEY" -w "$EC2_SECRET_KEY" || true
+ ec2-delete-disk-image -t "$taskId" --region "$region" \
+ -O "$AWS_ACCESS_KEY_ID" -W "$AWS_SECRET_ACCESS_KEY" \
+ -o "$AWS_ACCESS_KEY_ID" -w "$AWS_SECRET_ACCESS_KEY" || true
rm -f $stateDir/$region.$type.task-id
fi
# Create a snapshot.
if [ -z "$snapId" ]; then
echo "creating snapshot..."
- snapId=$(ec2-create-snapshot "$volId" --region "$region" | cut -f 2)
+ snapId=$(aws ec2 create-snapshot --volume-id "$volId" --region "$region" --description "$description" | jq -r .SnapshotId)
+ if [ "$snapId" = null ]; then exit 1; fi
echo -n "$snapId" > $stateDir/$region.$type.snap-id
- ec2-create-tags "$snapId" -t "Name=$description" --region "$region"
fi
# Wait for the snapshot to finish.
echo "waiting for snapshot to finish..."
while true; do
- status=$(ec2-describe-snapshots "$snapId" --region "$region" | head -n1 | cut -f 4)
+ status=$(aws ec2 describe-snapshots --snapshot-ids "$snapId" --region "$region" | jq -r .Snapshots[0].State)
if [ "$status" = completed ]; then break; fi
sleep 10
done
@@ -166,35 +174,50 @@ for type in hvm pv; do
# Delete the volume.
if [ -n "$volId" ]; then
echo "deleting volume..."
- ec2-delete-volume "$volId" --region "$region" || true
+ aws ec2 delete-volume --volume-id "$volId" --region "$region" || true
rm -f $stateDir/$region.$type.vol-id
fi
- extraFlags="-b /dev/sda1=$snapId:$vhdFileLogicalGigaBytes:true:gp2"
+ blockDeviceMappings="DeviceName=/dev/sda1,Ebs={SnapshotId=$snapId,VolumeSize=$vhdFileLogicalGigaBytes,DeleteOnTermination=true,VolumeType=gp2}"
+ extraFlags=""
if [ $type = pv ]; then
- extraFlags+=" --root-device-name=/dev/sda1"
+ extraFlags+=" --root-device-name /dev/sda1"
+ else
+ extraFlags+=" --root-device-name /dev/sda1"
+ extraFlags+=" --sriov-net-support simple"
+ extraFlags+=" --ena-support"
fi
- extraFlags+=" -b /dev/sdb=ephemeral0 -b /dev/sdc=ephemeral1 -b /dev/sdd=ephemeral2 -b /dev/sde=ephemeral3"
+ blockDeviceMappings+=" DeviceName=/dev/sdb,VirtualName=ephemeral0"
+ blockDeviceMappings+=" DeviceName=/dev/sdc,VirtualName=ephemeral1"
+ blockDeviceMappings+=" DeviceName=/dev/sdd,VirtualName=ephemeral2"
+ blockDeviceMappings+=" DeviceName=/dev/sde,VirtualName=ephemeral3"
+ fi
+
+ if [ $type = hvm ]; then
+ extraFlags+=" --sriov-net-support simple"
+ extraFlags+=" --ena-support"
fi
# Register the AMI.
if [ $type = pv ]; then
- kernel=$(ec2-describe-images -o amazon --filter "manifest-location=*pv-grub-hd0_1.04-$arch*" --region "$region" | cut -f 2)
- [ -n "$kernel" ]
+ kernel=$(aws ec2 describe-images --owner amazon --filters "Name=name,Values=pv-grub-hd0_1.04-$arch.gz" | jq -r .Images[0].ImageId)
+ if [ "$kernel" = null ]; then break; fi
echo "using PV-GRUB kernel $kernel"
extraFlags+=" --virtualization-type paravirtual --kernel $kernel"
else
extraFlags+=" --virtualization-type hvm"
fi
- ami=$(ec2-register \
- -n "$name" \
- -d "$description" \
+ ami=$(aws ec2 register-image \
+ --name "$name" \
+ --description "$description" \
--region "$region" \
--architecture "$arch" \
- $extraFlags | cut -f 2)
+ --block-device-mappings $blockDeviceMappings \
+ $extraFlags | jq -r .ImageId)
+ if [ "$ami" = null ]; then break; fi
fi
echo -n "$ami" > $amiFile
@@ -204,23 +227,45 @@ for type in hvm pv; do
ami=$(cat $amiFile)
fi
- if [ -z "$NO_WAIT" -o -z "$prevAmi" ]; then
- echo "waiting for AMI..."
- while true; do
- status=$(ec2-describe-images "$ami" --region "$region" | head -n1 | cut -f 5)
- if [ "$status" = available ]; then break; fi
- sleep 10
- done
-
- ec2-modify-image-attribute \
- --region "$region" "$ami" -l -a all
- fi
-
echo "region = $region, type = $type, store = $store, ami = $ami"
+
if [ -z "$prevAmi" ]; then
prevAmi="$ami"
prevRegion="$region"
fi
+ done
+
+ done
+
+done
+
+for type in $types; do
+ link=$stateDir/$type
+ system=x86_64-linux
+ arch=x86_64
+
+ for store in $stores; do
+
+ for region in $regions; do
+
+ name=nixos-$version-$arch-$type-$store
+ amiFile=$stateDir/$region.$type.$store.ami-id
+ ami=$(cat $amiFile)
+
+ echo "region = $region, type = $type, store = $store, ami = $ami"
+
+ echo -n "waiting for AMI..."
+ while true; do
+ status=$(aws ec2 describe-images --image-ids "$ami" --region "$region" | jq -r .Images[0].State)
+ if [ "$status" = available ]; then break; fi
+ sleep 10
+ echo -n '.'
+ done
+ echo
+
+ # Make the image public.
+ aws ec2 modify-image-attribute \
+ --image-id "$ami" --region "$region" --launch-permission 'Add={Group=all}'
echo " \"$major\".$region.$type-$store = \"$ami\";" >> ec2-amis.nix
done
diff --git a/nixos/modules/i18n/input-method/fcitx.nix b/nixos/modules/i18n/input-method/fcitx.nix
index bdefd2d2d59..e97bb9f80eb 100644
--- a/nixos/modules/i18n/input-method/fcitx.nix
+++ b/nixos/modules/i18n/input-method/fcitx.nix
@@ -4,7 +4,7 @@ with lib;
let
cfg = config.i18n.inputMethod.fcitx;
- fcitxPackage = pkgs.fcitx-with-plugins.override { plugins = cfg.engines; };
+ fcitxPackage = pkgs.fcitx.override { plugins = cfg.engines; };
fcitxEngine = types.package // {
name = "fcitx-engine";
check = x: (lib.types.package.check x) && (attrByPath ["meta" "isFcitxEngine"] false x);
diff --git a/nixos/modules/installer/tools/nixos-version.sh b/nixos/modules/installer/tools/nixos-version.sh
index 51aa2dd8232..77a1b458a34 100644
--- a/nixos/modules/installer/tools/nixos-version.sh
+++ b/nixos/modules/installer/tools/nixos-version.sh
@@ -1,6 +1,10 @@
#! @shell@
case "$1" in
+ -h|--help)
+ exec man nixos-version
+ exit 1
+ ;;
--hash|--revision)
echo "@nixosRevision@"
;;
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 034943be9e4..7a8491d6836 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -368,6 +368,7 @@
./services/networking/ntopng.nix
./services/networking/ntpd.nix
./services/networking/nylon.nix
+ ./services/networking/offlineimap.nix
./services/networking/oidentd.nix
./services/networking/openfire.nix
./services/networking/openntpd.nix
diff --git a/nixos/modules/programs/bash/inputrc b/nixos/modules/programs/bash/inputrc
index e4eabc052c5..f339eb649ed 100644
--- a/nixos/modules/programs/bash/inputrc
+++ b/nixos/modules/programs/bash/inputrc
@@ -6,6 +6,7 @@ set meta-flag on
set input-meta on
set convert-meta off
set output-meta on
+set colored-stats on
#set mark-symlinked-directories on
diff --git a/nixos/modules/services/games/factorio.nix b/nixos/modules/services/games/factorio.nix
index 10f3daea69e..90834c5b260 100644
--- a/nixos/modules/services/games/factorio.nix
+++ b/nixos/modules/services/games/factorio.nix
@@ -78,7 +78,7 @@ in
test -e ${stateDir}/saves/${cfg.saveName}.zip || \
${pkgs.factorio-headless}/bin/factorio \
--config=${cfg.configFile} \
- --create=${cfg.saveName}
+ --create=${stateDir}/saves/${cfg.saveName}.zip
'';
serviceConfig = {
@@ -93,7 +93,7 @@ in
"${pkgs.factorio-headless}/bin/factorio"
"--config=${cfg.configFile}"
"--port=${toString cfg.port}"
- "--start-server=${cfg.saveName}"
+ "--start-server=${stateDir}/saves/${cfg.saveName}.zip"
];
};
};
diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix
index c5dd1e71c18..633ceaebfa4 100644
--- a/nixos/modules/services/networking/ddclient.nix
+++ b/nixos/modules/services/networking/ddclient.nix
@@ -7,22 +7,8 @@ let
stateDir = "/var/spool/ddclient";
ddclientUser = "ddclient";
- ddclientFlags = "-foreground -verbose -noquiet -file ${ddclientCfg}";
+ ddclientFlags = "-foreground -verbose -noquiet -file /etc/ddclient.conf";
ddclientPIDFile = "${stateDir}/ddclient.pid";
- ddclientCfg = pkgs.writeText "ddclient.conf" ''
- daemon=600
- cache=${stateDir}/ddclient.cache
- pid=${ddclientPIDFile}
- use=${config.services.ddclient.use}
- login=${config.services.ddclient.username}
- password=${config.services.ddclient.password}
- protocol=${config.services.ddclient.protocol}
- server=${config.services.ddclient.server}
- ssl=${if config.services.ddclient.ssl then "yes" else "no"}
- wildcard=YES
- ${config.services.ddclient.domain}
- ${config.services.ddclient.extraConfig}
- '';
in
@@ -122,10 +108,30 @@ in
home = stateDir;
};
+ environment.etc."ddclient.conf" = {
+ uid = config.ids.uids.ddclient;
+ mode = "0600";
+ text = ''
+ daemon=600
+ cache=${stateDir}/ddclient.cache
+ pid=${ddclientPIDFile}
+ use=${config.services.ddclient.use}
+ login=${config.services.ddclient.username}
+ password=${config.services.ddclient.password}
+ protocol=${config.services.ddclient.protocol}
+ server=${config.services.ddclient.server}
+ ssl=${if config.services.ddclient.ssl then "yes" else "no"}
+ wildcard=YES
+ ${config.services.ddclient.domain}
+ ${config.services.ddclient.extraConfig}
+ '';
+ };
+
systemd.services.ddclient = {
description = "Dynamic DNS Client";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
+ restartTriggers = [ config.environment.etc."ddclient.conf".source ];
serviceConfig = {
# Uncomment this if too many problems occur:
diff --git a/nixos/modules/services/networking/offlineimap.nix b/nixos/modules/services/networking/offlineimap.nix
new file mode 100644
index 00000000000..31ce9280f31
--- /dev/null
+++ b/nixos/modules/services/networking/offlineimap.nix
@@ -0,0 +1,73 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.offlineimap;
+in {
+
+ options.services.offlineimap = {
+ enable = mkEnableOption "Offlineimap, a software to dispose your mailbox(es) as a local Maildir(s).";
+
+ install = mkOption {
+ type = types.bool;
+ default = false;
+ example = true;
+ description = ''
+ Whether to install a user service for Offlineimap. Once
+ the service is started, emails will be fetched automatically.
+
+ The service must be manually started for each user with
+ "systemctl --user start offlineimap" or globally through
+ services.offlineimap.enable.
+ '';
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.offlineimap;
+ defaultText = "pkgs.offlineimap";
+ description = "Offlineimap derivation to use.";
+ };
+
+ path = mkOption {
+ type = types.listOf types.path;
+ default = [];
+ example = literalExample "[ pkgs.pass pkgs.bash pkgs.notmuch ]";
+ description = "List of derivations to put in Offlineimap's path.";
+ };
+
+ onCalendar = mkOption {
+ type = types.str;
+ default = "*:0/3"; # every 3 minutes
+ description = "How often is offlineimap started. Default is '*:0/3' meaning every 3 minutes. See systemd.time(7) for more information about the format.";
+ };
+
+ timeoutStartSec = mkOption {
+ type = types.str;
+ default = "120sec"; # Kill if still alive after 2 minutes
+ description = "How long waiting for offlineimap before killing it. Default is '120sec' meaning every 2 minutes. See systemd.time(7) for more information about the format.";
+ };
+ };
+ config = mkIf (cfg.enable || cfg.install) {
+ systemd.user.services.offlineimap = {
+ description = "Offlineimap: a software to dispose your mailbox(es) as a local Maildir(s)";
+ serviceConfig = {
+ Type = "oneshot";
+ ExecStart = "${cfg.package}/bin/offlineimap -u basic -o -1";
+ TimeoutStartSec = cfg.timeoutStartSec;
+ };
+ path = cfg.path;
+ };
+ environment.systemPackages = [ "${cfg.package}" ];
+ systemd.user.timers.offlineimap = {
+ description = "offlineimap timer";
+ timerConfig = {
+ Unit = "offlineimap.service";
+ OnCalendar = cfg.onCalendar;
+ # start immediately after computer is started:
+ Persistent = "true";
+ };
+ } // optionalAttrs cfg.enable { wantedBy = [ "default.target" ]; };
+ };
+}
diff --git a/nixos/modules/system/boot/coredump.nix b/nixos/modules/system/boot/coredump.nix
index 793c7515c76..b27a35b6257 100644
--- a/nixos/modules/system/boot/coredump.nix
+++ b/nixos/modules/system/boot/coredump.nix
@@ -36,6 +36,8 @@ with lib;
config = mkMerge [
(mkIf config.systemd.coredump.enable {
+ systemd.additionalUpstreamSystemUnits = [ "systemd-coredump.socket" "systemd-coredump@.service" ];
+
environment.etc."systemd/coredump.conf".text =
''
[Coredump]
@@ -45,7 +47,7 @@ with lib;
# Have the kernel pass core dumps to systemd's coredump helper binary.
# From systemd's 50-coredump.conf file. See:
#
- boot.kernel.sysctl."kernel.core_pattern" = "|${pkgs.systemd}/lib/systemd/systemd-coredump %p %u %g %s %t %e";
+ boot.kernel.sysctl."kernel.core_pattern" = "|${pkgs.systemd}/lib/systemd/systemd-coredump %P %u %g %s %t %c %e";
})
(mkIf (!config.systemd.coredump.enable) {
diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix
index c5c250c14ce..576a07c1d27 100644
--- a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix
+++ b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.nix
@@ -5,5 +5,4 @@ pkgs.substituteAll {
isExecutable = true;
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
inherit (pkgs) bash;
- kernelDTB = pkgs.stdenv.platform.kernelDTB or false;
}
diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
index 78a8e8fd658..c780a89b102 100644
--- a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
+++ b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
@@ -75,9 +75,10 @@ addEntry() {
copyToKernelsDir "$path/kernel"; kernel=$result
copyToKernelsDir "$path/initrd"; initrd=$result
- if [ -n "@kernelDTB@" ]; then
- # XXX UGLY: maybe the system config should have a top-level "dtbs" entry?
- copyToKernelsDir $(readlink -m "$path/kernel/../dtbs"); dtbs=$result
+ # XXX UGLY: maybe the system config should have a top-level "dtbs" entry?
+ dtbDir=$(readlink -m "$path/kernel/../dtbs")
+ if [ -d "$dtbDir" ]; then
+ copyToKernelsDir "$dtbDir"; dtbs=$result
fi
timestampEpoch=$(stat -L -c '%Z' $path)
@@ -95,7 +96,7 @@ addEntry() {
fi
echo " LINUX ../nixos/$(basename $kernel)"
echo " INITRD ../nixos/$(basename $initrd)"
- if [ -n "@kernelDTB@" ]; then
+ if [ -d "$dtbDir" ]; then
echo " FDTDIR ../nixos/$(basename $dtbs)"
fi
echo " APPEND systemConfig=$path init=$path/init $extraParams"
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index b7c09d2e4bf..5c8cce5066a 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -764,7 +764,7 @@ in
{ wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = service.startAt;
})
- (filterAttrs (name: service: service.startAt != "") cfg.services);
+ (filterAttrs (name: service: service.enable && service.startAt != "") cfg.services);
# Generate timer units for all services that have a ‘startAt’ value.
systemd.user.timers =
diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix
index da5575f4b6d..ebf398fa266 100644
--- a/nixos/modules/virtualisation/amazon-image.nix
+++ b/nixos/modules/virtualisation/amazon-image.nix
@@ -20,8 +20,12 @@ let cfg = config.ec2; in
autoResize = true;
};
- boot.extraModulePackages = [ config.boot.kernelPackages.ixgbevf ];
- boot.initrd.kernelModules = [ "xen-blkfront" "xen-netfront" "ixgbevf" ];
+ boot.extraModulePackages =
+ [ config.boot.kernelPackages.ixgbevf
+ config.boot.kernelPackages.ena
+ ];
+ boot.initrd.kernelModules = [ "xen-blkfront" "xen-netfront" ];
+ boot.initrd.availableKernelModules = [ "ixgbevf" "ena" ];
boot.kernelParams = mkIf cfg.hvm [ "console=ttyS0" ];
# Prevent the nouveau kernel module from being loaded, as it
diff --git a/nixos/modules/virtualisation/ec2-amis.nix b/nixos/modules/virtualisation/ec2-amis.nix
index 5257aaf6202..bdf6ed4dcd2 100644
--- a/nixos/modules/virtualisation/ec2-amis.nix
+++ b/nixos/modules/virtualisation/ec2-amis.nix
@@ -90,40 +90,48 @@
"15.09".us-west-2.pv-ebs = "ami-005fb160";
"15.09".us-west-2.pv-s3 = "ami-cd55bbad";
- "16.03".ap-northeast-1.hvm-ebs = "ami-b6edf5d8";
- "16.03".ap-northeast-1.hvm-s3 = "ami-b1e3fbdf";
- "16.03".ap-northeast-1.pv-ebs = "ami-6190880f";
- "16.03".ap-northeast-1.pv-s3 = "ami-908d95fe";
- "16.03".ap-southeast-1.hvm-ebs = "ami-35b16656";
- "16.03".ap-southeast-1.hvm-s3 = "ami-41be6922";
- "16.03".ap-southeast-1.pv-ebs = "ami-4cb96e2f";
- "16.03".ap-southeast-1.pv-s3 = "ami-3bb96e58";
- "16.03".ap-southeast-2.hvm-ebs = "ami-debc91bd";
- "16.03".ap-southeast-2.hvm-s3 = "ami-55bc9136";
- "16.03".ap-southeast-2.pv-ebs = "ami-b38ba6d0";
- "16.03".ap-southeast-2.pv-s3 = "ami-9e8ba6fd";
- "16.03".eu-central-1.hvm-ebs = "ami-7c967413";
- "16.03".eu-central-1.hvm-s3 = "ami-b29072dd";
- "16.03".eu-central-1.pv-ebs = "ami-7a947615";
- "16.03".eu-central-1.pv-s3 = "ami-729b791d";
- "16.03".eu-west-1.hvm-ebs = "ami-ff27a98c";
- "16.03".eu-west-1.hvm-s3 = "ami-6c21af1f";
- "16.03".eu-west-1.pv-ebs = "ami-a33cb2d0";
- "16.03".eu-west-1.pv-s3 = "ami-ec38b69f";
- "16.03".sa-east-1.hvm-ebs = "ami-5bef6637";
- "16.03".sa-east-1.hvm-s3 = "ami-55f87139";
- "16.03".sa-east-1.pv-ebs = "ami-76e56c1a";
- "16.03".sa-east-1.pv-s3 = "ami-e1f8718d";
- "16.03".us-east-1.hvm-ebs = "ami-4bfd1926";
- "16.03".us-east-1.hvm-s3 = "ami-60c5210d";
- "16.03".us-east-1.pv-ebs = "ami-c0c92dad";
- "16.03".us-east-1.pv-s3 = "ami-f9d63294";
- "16.03".us-west-1.hvm-ebs = "ami-13aad473";
- "16.03".us-west-1.hvm-s3 = "ami-e1a8d681";
- "16.03".us-west-1.pv-ebs = "ami-c0a6d8a0";
- "16.03".us-west-1.pv-s3 = "ami-6aa9d70a";
- "16.03".us-west-2.hvm-ebs = "ami-265dad46";
- "16.03".us-west-2.hvm-s3 = "ami-cd40b0ad";
- "16.03".us-west-2.pv-ebs = "ami-7b4aba1b";
- "16.03".us-west-2.pv-s3 = "ami-0849b968";
+ "16.03".ap-northeast-1.hvm-ebs = "ami-40619d21";
+ "16.03".ap-northeast-1.hvm-s3 = "ami-ce629eaf";
+ "16.03".ap-northeast-1.pv-ebs = "ami-ef639f8e";
+ "16.03".ap-northeast-1.pv-s3 = "ami-a1609cc0";
+ "16.03".ap-northeast-2.hvm-ebs = "ami-deca00b0";
+ "16.03".ap-northeast-2.hvm-s3 = "ami-a3b77dcd";
+ "16.03".ap-northeast-2.pv-ebs = "ami-7bcb0115";
+ "16.03".ap-northeast-2.pv-s3 = "ami-a2b77dcc";
+ "16.03".ap-south-1.hvm-ebs = "ami-0dff9562";
+ "16.03".ap-south-1.hvm-s3 = "ami-13f69c7c";
+ "16.03".ap-south-1.pv-ebs = "ami-0ef39961";
+ "16.03".ap-south-1.pv-s3 = "ami-e0c8a28f";
+ "16.03".ap-southeast-1.hvm-ebs = "ami-5e964a3d";
+ "16.03".ap-southeast-1.hvm-s3 = "ami-4d964a2e";
+ "16.03".ap-southeast-1.pv-ebs = "ami-ec9b478f";
+ "16.03".ap-southeast-1.pv-s3 = "ami-999b47fa";
+ "16.03".ap-southeast-2.hvm-ebs = "ami-9f7359fc";
+ "16.03".ap-southeast-2.hvm-s3 = "ami-987359fb";
+ "16.03".ap-southeast-2.pv-ebs = "ami-a2705ac1";
+ "16.03".ap-southeast-2.pv-s3 = "ami-a3705ac0";
+ "16.03".eu-central-1.hvm-ebs = "ami-17a45178";
+ "16.03".eu-central-1.hvm-s3 = "ami-f9a55096";
+ "16.03".eu-central-1.pv-ebs = "ami-c8a550a7";
+ "16.03".eu-central-1.pv-s3 = "ami-6ea45101";
+ "16.03".eu-west-1.hvm-ebs = "ami-b5b3d5c6";
+ "16.03".eu-west-1.hvm-s3 = "ami-c986e0ba";
+ "16.03".eu-west-1.pv-ebs = "ami-b083e5c3";
+ "16.03".eu-west-1.pv-s3 = "ami-3c83e54f";
+ "16.03".sa-east-1.hvm-ebs = "ami-f6eb7f9a";
+ "16.03".sa-east-1.hvm-s3 = "ami-93e773ff";
+ "16.03".sa-east-1.pv-ebs = "ami-cbb82ca7";
+ "16.03".sa-east-1.pv-s3 = "ami-abb82cc7";
+ "16.03".us-east-1.hvm-ebs = "ami-c123a3d6";
+ "16.03".us-east-1.hvm-s3 = "ami-bc25a5ab";
+ "16.03".us-east-1.pv-ebs = "ami-bd25a5aa";
+ "16.03".us-east-1.pv-s3 = "ami-a325a5b4";
+ "16.03".us-west-1.hvm-ebs = "ami-748bcd14";
+ "16.03".us-west-1.hvm-s3 = "ami-a68dcbc6";
+ "16.03".us-west-1.pv-ebs = "ami-048acc64";
+ "16.03".us-west-1.pv-s3 = "ami-208dcb40";
+ "16.03".us-west-2.hvm-ebs = "ami-8263a0e2";
+ "16.03".us-west-2.hvm-s3 = "ami-925c9ff2";
+ "16.03".us-west-2.pv-ebs = "ami-5e61a23e";
+ "16.03".us-west-2.pv-s3 = "ami-734c8f13";
}
diff --git a/nixos/release.nix b/nixos/release.nix
index c8547784bbc..1800122fa2e 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -220,6 +220,7 @@ in rec {
tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; });
tests.dockerRegistry = hydraJob (import tests/docker-registry.nix { system = "x86_64-linux"; });
tests.dnscrypt-proxy = callTest tests/dnscrypt-proxy.nix { system = "x86_64-linux"; };
+ tests.ecryptfs = callTest tests/ecryptfs.nix {};
tests.etcd = hydraJob (import tests/etcd.nix { system = "x86_64-linux"; });
tests.ec2-nixops = hydraJob (import tests/ec2.nix { system = "x86_64-linux"; }).boot-ec2-nixops;
tests.ec2-config = hydraJob (import tests/ec2.nix { system = "x86_64-linux"; }).boot-ec2-config;
diff --git a/nixos/tests/ecryptfs.nix b/nixos/tests/ecryptfs.nix
new file mode 100644
index 00000000000..eceb25a0dea
--- /dev/null
+++ b/nixos/tests/ecryptfs.nix
@@ -0,0 +1,81 @@
+import ./make-test.nix ({ pkgs, ... }:
+{
+ name = "ecryptfs";
+
+ machine = { config, pkgs, ... }: {
+ imports = [ ./common/user-account.nix ];
+ boot.kernelModules = [ "ecryptfs" ];
+ security.pam.enableEcryptfs = true;
+ environment.systemPackages = with pkgs; [ keyutils ];
+ };
+
+ testScript = ''
+ $machine->waitForUnit("default.target");
+
+ # Set alice up with a password and a home
+ $machine->succeed("(echo foobar; echo foobar) | passwd alice");
+ $machine->succeed("chown -R alice.users ~alice");
+
+ # Migrate alice's home
+ my $out = $machine->succeed("echo foobar | ecryptfs-migrate-home -u alice");
+ $machine->log("ecryptfs-migrate-home said: $out");
+
+ # Log alice in (ecryptfs passwhrase is wrapped during first login)
+ $machine->sleep(2); # urgh: wait for username prompt
+ $machine->sendChars("alice\n");
+ $machine->sleep(1);
+ $machine->sendChars("foobar\n");
+ $machine->sleep(2);
+ $machine->sendChars("logout\n");
+ $machine->sleep(2);
+
+ # Why do I need to do this??
+ $machine->succeed("su alice -c ecryptfs-umount-private");
+ $machine->sleep(1);
+ $machine->fail("mount | grep ecryptfs"); # check that encrypted home is not mounted
+
+ # Show contents of the user keyring
+ my $out = $machine->succeed("su - alice -c 'keyctl list \@u'");
+ $machine->log("keyctl unlink said: " . $out);
+
+ # Log alice again
+ $machine->sendChars("alice\n");
+ $machine->sleep(1);
+ $machine->sendChars("foobar\n");
+ $machine->sleep(2);
+
+ # Create some files in encrypted home
+ $machine->succeed("su alice -c 'touch ~alice/a'");
+ $machine->succeed("su alice -c 'echo c > ~alice/b'");
+
+ # Logout
+ $machine->sendChars("logout\n");
+ $machine->sleep(2);
+
+ # Why do I need to do this??
+ $machine->succeed("su alice -c ecryptfs-umount-private");
+ $machine->sleep(1);
+
+ # Check that the filesystem is not accessible
+ $machine->fail("mount | grep ecryptfs");
+ $machine->succeed("su alice -c 'test \! -f ~alice/a'");
+ $machine->succeed("su alice -c 'test \! -f ~alice/b'");
+
+ # Log alice once more
+ $machine->sendChars("alice\n");
+ $machine->sleep(1);
+ $machine->sendChars("foobar\n");
+ $machine->sleep(2);
+
+ # Check that the files are there
+ $machine->sleep(1);
+ $machine->succeed("su alice -c 'test -f ~alice/a'");
+ $machine->succeed("su alice -c 'test -f ~alice/b'");
+ $machine->succeed(qq%test "\$(cat ~alice/b)" = "c"%);
+
+ # Catch https://github.com/NixOS/nixpkgs/issues/16766
+ $machine->succeed("su alice -c 'ls -lh ~alice/'");
+
+ $machine->sendChars("logout\n");
+ '';
+})
diff --git a/nixos/tests/gnome3_20-gdm.nix b/nixos/tests/gnome3_18-gdm.nix
similarity index 100%
rename from nixos/tests/gnome3_20-gdm.nix
rename to nixos/tests/gnome3_18-gdm.nix
diff --git a/nixos/tests/gnome3_20.nix b/nixos/tests/gnome3_18.nix
similarity index 95%
rename from nixos/tests/gnome3_20.nix
rename to nixos/tests/gnome3_18.nix
index 51c83a4e312..2c88e6abe89 100644
--- a/nixos/tests/gnome3_20.nix
+++ b/nixos/tests/gnome3_18.nix
@@ -15,7 +15,7 @@ import ./make-test.nix ({ pkgs, ...} : {
services.xserver.displayManager.auto.user = "alice";
services.xserver.desktopManager.gnome3.enable = true;
- environment.gnome3.packageSet = pkgs.gnome3_20;
+ environment.gnome3.packageSet = pkgs.gnome3_18;
virtualisation.memorySize = 512;
};
diff --git a/pkgs/applications/audio/i-score/default.nix b/pkgs/applications/audio/i-score/default.nix
index 17fadfe8b1f..97e8f5f1429 100644
--- a/pkgs/applications/audio/i-score/default.nix
+++ b/pkgs/applications/audio/i-score/default.nix
@@ -3,7 +3,7 @@
cln,
cmake,
fetchgit,
- gcc5,
+ gcc,
ginac,
jamomacore,
kde5,
@@ -37,7 +37,7 @@ stdenv.mkDerivation rec {
cln
cmake
ginac
- gcc5
+ gcc
jamomacore
kde5.kdnssd
libsndfile
diff --git a/pkgs/applications/editors/geany/default.nix b/pkgs/applications/editors/geany/default.nix
index b4f6baa9c64..cd93a4ed0e8 100644
--- a/pkgs/applications/editors/geany/default.nix
+++ b/pkgs/applications/editors/geany/default.nix
@@ -1,7 +1,7 @@
{ stdenv, fetchurl, gtk2, which, pkgconfig, intltool, file }:
let
- version = "1.27";
+ version = "1.28";
in
stdenv.mkDerivation rec {
@@ -9,7 +9,7 @@ stdenv.mkDerivation rec {
src = fetchurl {
url = "http://download.geany.org/${name}.tar.bz2";
- sha256 = "846ff699a5944c5c3c068ae0199d4c13946a668bfc6d03f8c79765667c20cadf";
+ sha256 = "0nha21rbdhl10vdpaq8d5v5fszvggl1xar555pvrnvm2y443ffpp";
};
buildInputs = [ gtk2 which pkgconfig intltool file ];
diff --git a/pkgs/applications/editors/idea/default.nix b/pkgs/applications/editors/idea/default.nix
index 6ef4edb5362..bc6f7fffeb3 100644
--- a/pkgs/applications/editors/idea/default.nix
+++ b/pkgs/applications/editors/idea/default.nix
@@ -189,13 +189,13 @@ in
idea-community = buildIdea rec {
name = "idea-community-${version}";
- version = "2016.1.3";
- build = "IC-145.1617.8";
+ version = "2016.2";
+ build = "IC-162.1121";
description = "Integrated Development Environment (IDE) by Jetbrains, community edition";
license = stdenv.lib.licenses.asl20;
src = fetchurl {
url = "https://download.jetbrains.com/idea/ideaIC-${version}.tar.gz";
- sha256 = "0yd1jqz4arywyjsiakszrr48w2xqnik6vnl1a6l0ph2hssgkzkfi";
+ sha256 = "164x4l0q31zpc1jh3js1xx9y6afrzsshmnkx1mwhmq8qmvzc4w32";
};
wmClass = "jetbrains-idea-ce";
};
@@ -228,13 +228,13 @@ in
idea-ultimate = buildIdea rec {
name = "idea-ultimate-${version}";
- version = "2016.1.3";
- build = "IU-145.1617.8";
+ version = "2016.2";
+ build = "IU-162.1121";
description = "Integrated Development Environment (IDE) by Jetbrains, requires paid license";
license = stdenv.lib.licenses.unfree;
src = fetchurl {
url = "https://download.jetbrains.com/idea/ideaIU-${version}.tar.gz";
- sha256 = "1zzxwdnw2bbnl86kj7fjk5p8c99d0hdn1ki2alw5xm8wp4k0w7rv";
+ sha256 = "10hiqh6ccmai2cnc5p72vqjcz9kzmmcpn0hy5v514h4mq6vs4zk4";
};
wmClass = "jetbrains-idea";
};
diff --git a/pkgs/applications/graphics/antimony/default.nix b/pkgs/applications/graphics/antimony/default.nix
index 8d17a290ceb..b7d9f4a8159 100644
--- a/pkgs/applications/graphics/antimony/default.nix
+++ b/pkgs/applications/graphics/antimony/default.nix
@@ -1,29 +1,25 @@
-{ stdenv, fetchgit, libpng, python3, boost, mesa, qtbase, qmakeHook, ncurses }:
+{ stdenv, fetchFromGitHub, libpng, python3, boost, mesa, qtbase, ncurses, cmake, flex, lemon }:
let
- gitRev = "745eca3a2d2657c495d5509e9083c884e021d09c";
+ gitRev = "e8480c718e8c49ae3cc2d7af10ea93ea4c2fff9a";
gitBranch = "master";
- gitTag = "0.8.0b";
+ gitTag = "0.9.2";
in
stdenv.mkDerivation rec {
name = "antimony-${version}";
version = gitTag;
- src = fetchgit {
- url = "git://github.com/mkeeter/antimony.git";
- rev = gitRev;
- sha256 = "0azjdkbixz2pyk2yy7a0ya5xk60xgw3l2pd4pj4ijyqxx5jmh0sy";
+ src = fetchFromGitHub {
+ owner = "mkeeter";
+ repo = "antimony";
+ rev = gitTag;
+ sha256 = "0fpgy5cb4knz2z9q078206k8wzxfs8b9g76mf4bz1ic77931ykjz";
};
patches = [ ./paths-fix.patch ];
- # fix build with glibc-2.23
+
postPatch = ''
- sed 's/\ /dev/null)
--GITBRANCH = $$system(git rev-parse --abbrev-ref HEAD)
+-execute_process(COMMAND git log --pretty=format:'%h' -n 1
+- OUTPUT_VARIABLE GITREV)
+-execute_process(COMMAND bash -c "git diff --quiet --exit-code || echo +"
+- OUTPUT_VARIABLE GITDIFF)
+-execute_process(COMMAND git describe --exact-match --tags
+- OUTPUT_VARIABLE GITTAG
+- ERROR_QUIET)
+-execute_process(COMMAND git rev-parse --abbrev-ref HEAD
+- OUTPUT_VARIABLE GITBRANCH)
-
--QMAKE_CXXFLAGS += "-D'GITREV=\"$${GITREV}$${GITDIFF}\"'"
--QMAKE_CXXFLAGS += "-D'GITTAG=\"$${GITTAG}\"'"
--QMAKE_CXXFLAGS += "-D'GITBRANCH=\"$${GITBRANCH}\"'"
-+QMAKE_CXXFLAGS += "-D'GITREV=\"$$(GITREV)\"'"
-+QMAKE_CXXFLAGS += "-D'GITTAG=\"$$(GITTAG)\"'"
-+QMAKE_CXXFLAGS += "-D'GITBRANCH=\"$$(GITBRANCH)\"'"
-
- OLD_GL_SET = $$(OLD_GL)
- equals(OLD_GL_SET, "true") {
-@@ -125,11 +120,11 @@ macx {
- }
-
- linux {
-- executable.path = /usr/local/bin
-+ executable.path = $$(out)/bin
- executable.files = antimony
-- nodes_folder.path = /usr/local/bin/sb/nodes
-+ nodes_folder.path = $$(out)/bin/sb/nodes
- nodes_folder.files = ../py/nodes/*
-- fab_folder.path = /usr/local/bin/sb/fab
-+ fab_folder.path = $$(out)/bin/sb/fab
- fab_folder.files = ../py/fab/*
- INSTALLS += executable nodes_folder fab_folder
- }
-diff --git a/qt/fab.pri b/qt/fab.pri
-index a54813b..b500536 100644
---- a/qt/fab.pri
-+++ b/qt/fab.pri
-@@ -54,7 +54,7 @@ DEFINES += '_STATIC_= '
-
- linux {
- QMAKE_CFLAGS += -std=gnu99
-- QMAKE_CXXFLAGS += $$system(/usr/bin/python3-config --includes)
-+ QMAKE_CXXFLAGS += $$system(python3-config --includes)
- LIBS += -lpng
- }
-
-diff --git a/qt/shared.pri b/qt/shared.pri
-index e7d0e3a..026eae3 100644
---- a/qt/shared.pri
-+++ b/qt/shared.pri
-@@ -39,41 +39,11 @@ macx {
- }
-
- linux {
-- QMAKE_CXXFLAGS += $$system(/usr/bin/python3-config --includes)
-- QMAKE_LFLAGS += $$system(/usr/bin/python3-config --ldflags)
-+ QMAKE_CXXFLAGS += $$system(python3-config --includes)
-+ QMAKE_LFLAGS += $$system(python3-config --ldflags)
-
- # Even though this is in QMAKE_LFLAGS, the linker is picky about
- # library ordering (so it needs to be here too).
- LIBS += -lpython3.4m
--
-- # ldconfig is being used to find libboost_python, but it's in a different
-- # place in different distros (and is not in the default $PATH on Debian).
-- # First, check to see if it's on the default $PATH.
-- system(which ldconfig > /dev/null) {
-- LDCONFIG_BIN = "ldconfig"
-- }
-- # If that failed, then search for it in its usual places.
-- isEmpty(LDCONFIG_BIN) {
-- for(p, $$list(/sbin/ldconfig /usr/bin/ldconfig)) {
-- exists($$p): LDCONFIG_BIN = $$p
-- }
-- }
-- # If that search failed too, then exit with an error.
-- isEmpty(LDCONFIG_BIN) {
-- error("Could not find ldconfig!")
-- }
--
-- # Check for different boost::python naming schemes
-- LDCONFIG_OUT = $$system($$LDCONFIG_BIN -p|grep python)
-- for (b, $$list(boost_python-py34 boost_python3)) {
-- contains(LDCONFIG_OUT, "lib$${b}.so") {
-- LIBS += "-l$$b"
-- GOT_BOOST_PYTHON = True
-- }
-- }
--
-- # If we couldn't find boost::python, exit with an error.
-- isEmpty(GOT_BOOST_PYTHON) {
-- error("Could not find boost::python3")
-- }
-+ LIBS += -lboost_python3
- }
+ add_definitions(-D'GITREV="${GITREV}${GITDIFF}"'
+ -D'GITTAG="${GITTAG}"'
+ -D'GITBRANCH="${GITBRANCH}"')
diff --git a/pkgs/applications/graphics/feh/default.nix b/pkgs/applications/graphics/feh/default.nix
index 2d7b8874246..a20a1be77f8 100644
--- a/pkgs/applications/graphics/feh/default.nix
+++ b/pkgs/applications/graphics/feh/default.nix
@@ -2,11 +2,11 @@
, libXinerama, curl, libexif, perlPackages }:
stdenv.mkDerivation rec {
- name = "feh-2.15.4";
+ name = "feh-2.16.1";
src = fetchurl {
url = "http://feh.finalrewind.org/${name}.tar.bz2";
- sha256 = "b8a9c29f37b1349228b19866f712b677e2a150837bc46be8c5d6348dd4850758";
+ sha256 = "1cxnc8dxyl7s4qnkvdjaqx7gdvc6brxpq0qbg91mljg47fd2hmbf";
};
outputs = [ "out" "doc" ];
diff --git a/pkgs/applications/graphics/graphicsmagick/default.nix b/pkgs/applications/graphics/graphicsmagick/default.nix
index 63b88ee4fb9..b780067823a 100644
--- a/pkgs/applications/graphics/graphicsmagick/default.nix
+++ b/pkgs/applications/graphics/graphicsmagick/default.nix
@@ -2,14 +2,14 @@
, libjpeg, libpng, libtiff, libxml2, zlib, libtool, xz
, libX11, libwebp, quantumdepth ? 8}:
-let version = "1.3.23"; in
+let version = "1.3.24"; in
stdenv.mkDerivation {
name = "graphicsmagick-${version}";
src = fetchurl {
url = "mirror://sourceforge/graphicsmagick/GraphicsMagick-${version}.tar.xz";
- sha256 = "03g6l2h8cmf231y1vma0z7x85070jm1ysgs9ppqcd3jj56jka9gx";
+ sha256 = "1q40w5hcl8rcpszm0r7rpr3a9lj390p39zfvavkvlgxyyk7bmgsj";
};
patches = [ ./disable-popen.patch ];
diff --git a/pkgs/applications/misc/iterm2/default.nix b/pkgs/applications/misc/iterm2/default.nix
index add16365324..028e5d6b725 100644
--- a/pkgs/applications/misc/iterm2/default.nix
+++ b/pkgs/applications/misc/iterm2/default.nix
@@ -2,13 +2,13 @@
stdenv.mkDerivation rec {
name = "iterm2-${version}";
- version = "3.0.2";
+ version = "3.0.4";
src = fetchFromGitHub {
owner = "gnachman";
repo = "iTerm2";
rev = "v${version}";
- sha256 = "121g759i814y1g1g1jwhsmxgg4wrzv08vq7a7qwc7b85a17zbd3h";
+ sha256 = "0ffg9l2jvv503h13nd5rjkn5xrahswcqqwmm052qzd6d0lmqjm93";
};
patches = [ ./disable_updates.patch ];
diff --git a/pkgs/applications/misc/lighthouse/Makefile.patch b/pkgs/applications/misc/lighthouse/Makefile.patch
new file mode 100644
index 00000000000..0207299cc2c
--- /dev/null
+++ b/pkgs/applications/misc/lighthouse/Makefile.patch
@@ -0,0 +1,31 @@
+# Description: Fix lighthouse Makefile
+Index: Makefile
+===================================================================
+--- ./Makefile 1970-01-01 02:00:01.000000000 +0200
++++ ./Makefile 1970-01-01 02:00:01.000000000 +0200
+@@ -19,21 +19,10 @@
+ endif
+
+ # Library specific
+-HAS_GDK := $(shell pkg-config --exists gdk-2.0 echo $?)
+-ifdef $(HAS_GDK)
+- CFLAGS+=`pkg-config --cflags gdk-2.0`
+- LDFLAGS+=`pkg-config --libs gdk-2.0`
+-else
+- CFLAGS+=-DNO_GDK
+-endif
+-HAS_PANGO := $(shell pkg-config --exists pango echo $?)
+-ifdef $(HAS_PANGO)
+- CFLAGS+=`pkg-config --cflags pango`
+- LDFLAGS+=`pkg-config --libs pango`
+-else
+- CFLAGS+=-DNO_PANGO
+-endif
+-
++CFLAGS+=$(shell pkg-config --cflags gdk-2.0)
++LDFLAGS+=$(shell pkg-config --libs gdk-2.0)
++CFLAGS+=$(shell pkg-config --cflags pango)
++LDFLAGS+=$(shell pkg-config --libs pango)
+
+ all: lighthouse
+
diff --git a/pkgs/applications/misc/lighthouse/default.nix b/pkgs/applications/misc/lighthouse/default.nix
new file mode 100644
index 00000000000..8400c01665e
--- /dev/null
+++ b/pkgs/applications/misc/lighthouse/default.nix
@@ -0,0 +1,49 @@
+{ stdenv, fetchFromGitHub, pkgconfig
+, libX11, libxcb, cairo, gtk, pango, python27, python3
+}:
+
+stdenv.mkDerivation rec {
+ name = "lighthouse-${date}";
+ date = "2016-01-26";
+
+ src = fetchFromGitHub {
+ owner = "emgram769";
+ repo = "lighthouse";
+ rev = "bf11f111572475e855b0329202a14c9e128c7e57";
+ sha256 = "1ppika61vg4sc9mczbkjqy2mhgxqg57xrnsmmq0h2lyvj0yhg3qn";
+ };
+
+ buildInputs = [
+ pkgconfig libX11 libxcb cairo gtk pango python27 python3
+ ];
+
+ patches = [ ./Makefile.patch ];
+
+ lighthouseInstaller = ''
+ #!${stdenv.shell}
+ cp -r $out/share/lighthouse/.config/lighthouse \$HOME/.config
+ chmod -R +w \$HOME/.config/lighthouse
+ '';
+
+ installPhase = ''
+ mkdir -p $out/bin
+ cp lighthouse $out/bin
+ chmod +x config/lighthouse/cmd*
+ chmod +x config/lighthouse/google.py
+ patchShebangs config/lighthouse/
+ patchShebangs config/lighthouse/scripts/
+ mkdir -p $out/share/lighthouse/.config
+ cp -r config/lighthouse $out/share/lighthouse/.config
+ echo "${lighthouseInstaller}" > $out/bin/lighthouse-install
+ chmod +x $out/bin/lighthouse-install
+ '';
+
+ meta = with stdenv.lib; {
+ description = "A simple flexible popup dialog to run on X";
+ homepage = https://github.com/emgram769/lighthouse;
+ license = licenses.mit;
+ maintainers = with maintainers; [ ramkromberg ];
+ platforms = platforms.linux;
+ };
+
+}
diff --git a/pkgs/applications/misc/mop/default.nix b/pkgs/applications/misc/mop/default.nix
new file mode 100644
index 00000000000..ccdb47c4b60
--- /dev/null
+++ b/pkgs/applications/misc/mop/default.nix
@@ -0,0 +1,30 @@
+{ stdenv, lib, buildGoPackage, fetchgit }:
+
+buildGoPackage rec {
+ name = "mop-${version}";
+ version = "0.2.0";
+ rev = "bc666ec165d08b43134f7ec0bf29083ad5466243";
+
+ goPackagePath = "github.com/michaeldv/mop";
+ goDeps = ./deps.json;
+
+ preConfigure = ''
+ for i in $(find . -type f);do
+ substituteInPlace $i --replace michaeldv/termbox-go nsf/termbox-go
+ done
+ substituteInPlace Makefile --replace mop/cmd mop/mop
+ mv cmd mop
+ '';
+
+ src = fetchgit {
+ inherit rev;
+ url = "https://github.com/mop-tracker/mop";
+ sha256 = "0zp51g9i8rw6acs4vnrxclbxa5z1v0a0m1xx27szszp0rphcczkx";
+ };
+
+ meta = {
+ description = "Simple stock tracker implemented in go";
+ homepage = https://github.com/mop-tracker/mop;
+ platforms = stdenv.lib.platforms.all;
+ };
+}
diff --git a/pkgs/applications/misc/mop/deps.json b/pkgs/applications/misc/mop/deps.json
new file mode 100644
index 00000000000..e1b40df8310
--- /dev/null
+++ b/pkgs/applications/misc/mop/deps.json
@@ -0,0 +1,8 @@
+[
+ {
+ "include": "../../libs.json",
+ "packages": [
+ "github.com/nsf/termbox-go"
+ ]
+ }
+]
diff --git a/pkgs/applications/misc/pdfmod/default.nix b/pkgs/applications/misc/pdfmod/default.nix
index 24a0a8c6967..0978da3512b 100644
--- a/pkgs/applications/misc/pdfmod/default.nix
+++ b/pkgs/applications/misc/pdfmod/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchurl, fetchpatch, pkgconfig, gnome_doc_utils, intltool
+{ stdenv, fetchurl, fetchpatch, pkgconfig, gnome_doc_utils, intltool, lib
, mono, gtk-sharp, gnome-sharp, hyena
, which, makeWrapper, glib, gnome3, poppler, wrapGAppsHook
}:
@@ -33,12 +33,7 @@ stdenv.mkDerivation rec {
--add-flags "$out/lib/pdfmod/PdfMod.exe" \
--prefix MONO_GAC_PREFIX : ${gtk-sharp} \
--prefix MONO_GAC_PREFIX : ${gnome-sharp} \
- --prefix LD_LIBRARY_PATH : ${glib}/lib \
- --prefix LD_LIBRARY_PATH : ${gtk-sharp}/lib \
- --prefix LD_LIBRARY_PATH : ${gnome-sharp}/lib \
- --prefix LD_LIBRARY_PATH : ${gtk-sharp.gtk}/lib \
- --prefix LD_LIBRARY_PATH : ${gnome3.gconf}/lib \
- --prefix LD_LIBRARY_PATH : ${poppler.out}/lib
+ --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ glib gnome-sharp gnome3.gconf gtk-sharp gtk-sharp.gtk poppler ]}
'';
dontStrip = true;
diff --git a/pkgs/applications/networking/browsers/firefox-bin/default.nix b/pkgs/applications/networking/browsers/firefox-bin/default.nix
index 26030e33e48..e9f6f816be5 100644
--- a/pkgs/applications/networking/browsers/firefox-bin/default.nix
+++ b/pkgs/applications/networking/browsers/firefox-bin/default.nix
@@ -42,12 +42,9 @@ assert stdenv.isLinux;
let
- generated = if channel == "stable" then (import ./sources.nix)
- else if channel == "beta" then (import ./beta_sources.nix)
- else if channel == "developer" then { version = "49.0a2"; sources = [
- { locale = "en-US"; arch = "linux-i686"; sha512 = "45dad182bf7a4e753c1be6b8f966393a06531e7b5530238d20cb67b26324e8f5d0eeec983a0855418f31187d3ae508c28810ab86269848b4e48ab2ca3b5d21e7"; }
- { locale = "en-US"; arch = "linux-x86_64"; sha512 = "cfcbfc633b51612a62267c8a1afc25af212eb832d1fa876a1ffd82421e9378f96b3ac1488446f804518290abd99c21c9f10e4d0e0f699432aeb74b63305d7edc"; }
- ]; }
+ generated = if channel == "stable" then (import ./sources.nix)
+ else if channel == "beta" then (import ./beta_sources.nix)
+ else if channel == "developer" then (import ./dev_sources.nix)
else builtins.abort "Wrong channel! Channel must be one of `stable`, `beta` or `developer`";
inherit (generated) version sources;
diff --git a/pkgs/applications/networking/browsers/firefox-bin/dev_sources.nix b/pkgs/applications/networking/browsers/firefox-bin/dev_sources.nix
new file mode 100644
index 00000000000..f43810d53f0
--- /dev/null
+++ b/pkgs/applications/networking/browsers/firefox-bin/dev_sources.nix
@@ -0,0 +1,12 @@
+# This file is generated from generate_sources_dev.rb. DO NOT EDIT.
+# Execute the following command to update the file.
+#
+# ruby generate_sources_dev.rb 49.0a2 > dev_sources.nix
+
+{
+ version = "49.0a2";
+ sources = [
+ { locale = "en-US"; arch = "linux-i686"; sha512 = "85c4289e561d2246f96a05e3b8df011337984b9f176670826a705c2cd68a1284056ba507e4b6e4887595bf37f25386d9f7b28a20bc1f125865b9fd7b8be17eaa"; }
+ { locale = "en-US"; arch = "linux-x86_64"; sha512 = "2bf9518dbfbb48348f74929c19d03e8daf51020bf9ba6db577a202b6e98ad7ffb9e9a0b4ca92af010cd3f864ae84940b65438f4230e6de3165f72e4e7280086d"; }
+ ];
+}
diff --git a/pkgs/applications/networking/browsers/firefox-bin/generate_sources_dev.rb b/pkgs/applications/networking/browsers/firefox-bin/generate_sources_dev.rb
new file mode 100644
index 00000000000..37d5569efb0
--- /dev/null
+++ b/pkgs/applications/networking/browsers/firefox-bin/generate_sources_dev.rb
@@ -0,0 +1,53 @@
+#!/usr/bin/env ruby
+require "open-uri"
+
+version =
+ if ARGV.empty?
+ $stderr.puts("Usage: ruby generate_sources_dev.rb > dev_sources.nix")
+ exit(-1)
+ else
+ ARGV[0]
+ end
+
+base_url = "http://download-installer.cdn.mozilla.net/pub/firefox/nightly/latest-mozilla-aurora"
+
+arches = ["linux-i686", "linux-x86_64"]
+locales = ["en-US"]
+sources = []
+
+Source = Struct.new(:hash, :arch, :locale, :filename)
+
+locales.each do |locale|
+ arches.each do |arch|
+ basename = "firefox-#{version}.#{locale}.#{arch}"
+ filename = basename + ".tar.bz2"
+ sha512 = open("#{base_url}/#{basename}.checksums").each_line
+ .find(filename).first
+ .split(" ").first
+ sources << Source.new(sha512, arch, locale, filename)
+ end
+end
+
+sources = sources.sort_by do |source|
+ [source.locale, source.arch]
+end
+
+puts(<<"EOH")
+# This file is generated from generate_sources_dev.rb. DO NOT EDIT.
+# Execute the following command to update the file.
+#
+# ruby generate_sources_dev.rb 49.0a2 > dev_sources.nix
+
+{
+ version = "#{version}";
+ sources = [
+EOH
+
+sources.each do |source|
+ puts(%Q| { locale = "#{source.locale}"; arch = "#{source.arch}"; sha512 = "#{source.hash}"; }|)
+end
+
+puts(<<'EOF')
+ ];
+}
+EOF
diff --git a/pkgs/applications/networking/browsers/mozilla-plugins/bluejeans/default.nix b/pkgs/applications/networking/browsers/mozilla-plugins/bluejeans/default.nix
index 147540ed158..574fd9efdd4 100644
--- a/pkgs/applications/networking/browsers/mozilla-plugins/bluejeans/default.nix
+++ b/pkgs/applications/networking/browsers/mozilla-plugins/bluejeans/default.nix
@@ -17,11 +17,11 @@ in
stdenv.mkDerivation rec {
name = "bluejeans-${version}";
- version = "2.160.49.8";
+ version = "2.160.63.8";
src = fetchurl {
url = "https://swdl.bluejeans.com/skinny/bjnplugin_${version}-1_amd64.deb";
- sha256 = "1hf4jx0d1wiv622rwck0mm8cckm121yszviw47jsw0mjnp91hqch";
+ sha256 = "1sfz9xvvrbw7gg7fxxwg9wmgbxgv3fa14p7i4m85mg10l3qxaqfc";
};
phases = [ "unpackPhase" "installPhase" "fixupPhase" ];
diff --git a/pkgs/applications/networking/ftp/filezilla/default.nix b/pkgs/applications/networking/ftp/filezilla/default.nix
index 4b7b56c69ea..5d92f7455d6 100644
--- a/pkgs/applications/networking/ftp/filezilla/default.nix
+++ b/pkgs/applications/networking/ftp/filezilla/default.nix
@@ -1,13 +1,13 @@
{ stdenv, fetchurl, dbus, gnutls, wxGTK30, libidn, tinyxml, gettext
, pkgconfig, xdg_utils, gtk2, sqlite, pugixml, libfilezilla, nettle }:
-let version = "3.18.0"; in
+let version = "3.19.0"; in
stdenv.mkDerivation {
name = "filezilla-${version}";
src = fetchurl {
url = "mirror://sourceforge/project/filezilla/FileZilla_Client/${version}/FileZilla_${version}_src.tar.bz2";
- sha256 = "1qnpbx2684r529ldih6fi5anjlcgqn2xfcls0q38iadrk1qnqr1p";
+ sha256 = "0827z1jmn8pkzrcpjgh5yh2r23vgv73yb4rikraxa9i7l118g9l2";
};
configureFlags = [
diff --git a/pkgs/applications/networking/instant-messengers/zoom-us/default.nix b/pkgs/applications/networking/instant-messengers/zoom-us/default.nix
new file mode 100644
index 00000000000..7f4a27cf9a2
--- /dev/null
+++ b/pkgs/applications/networking/instant-messengers/zoom-us/default.nix
@@ -0,0 +1,105 @@
+{ alsaLib
+, fetchurl
+, gcc
+, glib
+, gst_plugins_base
+, gstreamer
+, icu_54_1
+, libpulseaudio
+, libuuid
+, libxml2
+, libxslt
+, makeQtWrapper
+, qt55
+, sqlite
+, stdenv
+, xlibs
+, xorg
+, zlib
+}:
+
+stdenv.mkDerivation rec {
+ name = "zoom-us";
+ meta = {
+ homepage = http://zoom.us;
+ description = "zoom.us instant messenger";
+ license = stdenv.lib.licenses.unfree;
+ platforms = stdenv.lib.platforms.linux;
+ };
+
+ version = "2.0.52458.0531";
+ src = fetchurl {
+ url = "https://zoom.us/client/latest/zoom_${version}_x86_64.tar.xz";
+ sha256 = "16d64pn9j27v3fnh4c9i32vpkr10q1yr26w14964n0af1mv5jf7a";
+ };
+
+ phases = [ "unpackPhase" "installPhase" ];
+ nativeBuildInputs = [ makeQtWrapper ];
+ libPath = stdenv.lib.makeLibraryPath [
+ alsaLib
+ gcc.cc
+ glib
+ gst_plugins_base
+ gstreamer
+ icu_54_1
+ libpulseaudio
+ libuuid
+ libxml2
+ libxslt
+ qt55.qtbase
+ qt55.qtdeclarative
+ qt55.qtscript
+ qt55.qtwebkit
+ sqlite
+ xlibs.xcbutilkeysyms
+ xorg.libX11
+ xorg.libxcb
+ xorg.libXcomposite
+ xorg.libXext
+ xorg.libXfixes
+ xorg.libXrender
+ xorg.xcbutilimage
+ zlib
+ ];
+ installPhase = ''
+ mkdir -p $out/share
+ cp -r \
+ application-x-zoom.png \
+ audio \
+ imageformats \
+ chrome.bmp \
+ config-dump.sh \
+ dingdong1.pcm \
+ dingdong.pcm \
+ doc \
+ Droplet.pcm \
+ Droplet.wav \
+ platforminputcontexts \
+ platforms \
+ platformthemes \
+ Qt \
+ QtMultimedia \
+ QtQml \
+ QtQuick \
+ QtQuick.2 \
+ QtWebKit \
+ QtWebProcess \
+ ring.pcm \
+ ring.wav \
+ version.txt \
+ xcbglintegrations \
+ zcacert.pem \
+ zoom \
+ Zoom.png \
+ ZXMPPROOT.cer \
+ $out/share
+
+ patchelf \
+ --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
+ --set-rpath ${libPath} \
+ $out/share/zoom
+ wrapQtProgram "$out/share/zoom"
+ mkdir -p $out/bin
+ ln -s $out/share/zoom $out/bin/zoom-us
+ '';
+ }
diff --git a/pkgs/applications/networking/mailreaders/mutt/default.nix b/pkgs/applications/networking/mailreaders/mutt/default.nix
index 1964faf2f5c..31ead22e1fd 100644
--- a/pkgs/applications/networking/mailreaders/mutt/default.nix
+++ b/pkgs/applications/networking/mailreaders/mutt/default.nix
@@ -1,43 +1,51 @@
{ stdenv, fetchurl, ncurses, which, perl, autoreconfHook
-, sslSupport ? true
-, imapSupport ? true
-, headerCache ? true
-, saslSupport ? true
-, gpgmeSupport ? true
, gdbm ? null
, openssl ? null
, cyrus_sasl ? null
, gpgme ? null
-, withSidebar ? false
+, aclocal ? null
+, headerCache ? true
+, sslSupport ? true
+, saslSupport ? true
+, gpgmeSupport ? true
+, imapSupport ? true
+, withSidebar ? false
+, withTrash ? false
}:
-assert headerCache -> gdbm != null;
-assert sslSupport -> openssl != null;
-assert saslSupport -> cyrus_sasl != null;
-assert gpgmeSupport -> gpgme != null;
+assert headerCache -> gdbm != null;
+assert sslSupport -> openssl != null;
+assert saslSupport -> cyrus_sasl != null;
+assert gpgmeSupport -> gpgme != null;
+
+with stdenv.lib;
-let
- version = "1.6.0";
-in
stdenv.mkDerivation rec {
- name = "mutt${stdenv.lib.optionalString withSidebar "-with-sidebar"}-${version}";
+ name = "mutt-${version}";
+ version = "1.6.2";
src = fetchurl {
- url = "http://ftp.mutt.org/pub/mutt/mutt-${version}.tar.gz";
- sha256 = "06bc2drbgalkk68rzg7hq2v5m5qgjxff5357wg0419dpi8ivdbr9";
+ url = "http://ftp.mutt.org/pub/mutt/${name}.tar.gz";
+ sha256 = "13hxmji7v9m2agmvzrs7gzx8s3c9jiwrv7pbkr7z1kc6ckq2xl65";
};
- buildInputs = with stdenv.lib;
+ buildInputs =
[ ncurses which perl ]
- ++ optional headerCache gdbm
- ++ optional sslSupport openssl
- ++ optional saslSupport cyrus_sasl
- ++ optional gpgmeSupport gpgme;
-
- nativeBuildInputs = stdenv.lib.optional withSidebar autoreconfHook;
+ ++ optional headerCache gdbm
+ ++ optional sslSupport openssl
+ ++ optional saslSupport cyrus_sasl
+ ++ optional gpgmeSupport gpgme
+ ++ optional withSidebar autoreconfHook;
configureFlags = [
- "--with-mailpath=" "--enable-smtp"
+ (enableFeature headerCache "hcache")
+ (enableFeature gpgmeSupport "gpgme")
+ (enableFeature imapSupport "imap")
+ (enableFeature withSidebar "sidebar")
+ "--enable-smtp"
+ "--enable-pop"
+ "--enable-imap"
+ "--with-mailpath="
# Look in $PATH at runtime, instead of hardcoding /usr/bin/sendmail
"ac_cv_path_SENDMAIL=sendmail"
@@ -45,36 +53,22 @@ stdenv.mkDerivation rec {
# This allows calls with "-d N", that output debug info into ~/.muttdebug*
"--enable-debug"
- "--enable-pop" "--enable-imap"
-
# The next allows building mutt without having anything setgid
# set by the installer, and removing the need for the group 'mail'
# I set the value 'mailbox' because it is a default in the configure script
"--with-homespool=mailbox"
- (if headerCache then "--enable-hcache" else "--disable-hcache")
- (if sslSupport then "--with-ssl" else "--without-ssl")
- (if imapSupport then "--enable-imap" else "--disable-imap")
- (if saslSupport then "--with-sasl" else "--without-sasl")
- (if gpgmeSupport then "--enable-gpgme" else "--disable-gpgme")
- ];
+ ] ++ optional sslSupport "--with-ssl"
+ ++ optional saslSupport "--with-sasl";
- # Adding the sidebar
- patches = stdenv.lib.optional withSidebar [
- ./trash-folder.patch
- ./sidebar.patch
- ./sidebar-dotpathsep.patch
- ./sidebar-utf8.patch
- ./sidebar-newonly.patch
- ./sidebar-delimnullwide.patch
- ./sidebar-compose.patch
- ./sidebar-new.patch
- ];
+ patches =
+ optional withTrash ./trash.patch ++
+ optional withSidebar ./sidebar.patch;
- meta = with stdenv.lib; {
+ meta = {
description = "A small but very powerful text-based mail client";
homepage = http://www.mutt.org;
- license = stdenv.lib.licenses.gpl2Plus;
+ license = licenses.gpl2Plus;
platforms = platforms.unix;
- maintainers = with maintainers; [ the-kenny ];
+ maintainers = with maintainers; [ the-kenny rnhmjoj ];
};
}
diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-compose.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-compose.patch
deleted file mode 100644
index 90d815b841d..00000000000
--- a/pkgs/applications/networking/mailreaders/mutt/sidebar-compose.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From: Evgeni Golov
-Date: Fri, 14 Mar 2014 08:54:47 +0100
-Subject: sidebar-compose
-
-draw_sidebar sets SidebarWidth to 0 when sidebar_visible is false.
-However, if you start mutt in compose mode, draw_sidebar won't be
-called until the next redraw and your header lines will be off by
-the width of the sidebar, even when you did not want a sidebar at
-all.
-
-Can be tested with:
- HOME=/ LC_ALL=C mutt -e 'unset sidebar_visible' -s test recipient
-
-Closes: #502627
-
-Gbp-Pq: Topic mutt-patched
----
- compose.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/compose.c b/compose.c
-index b63695f..0fa6df2 100644
---- a/compose.c
-+++ b/compose.c
-@@ -32,6 +32,7 @@
- #include "mailbox.h"
- #include "sort.h"
- #include "charset.h"
-+#include "sidebar.h"
-
- #ifdef MIXMASTER
- #include "remailer.h"
-@@ -248,6 +249,7 @@ static void draw_envelope_addr (int line, ADDRESS *addr)
-
- static void draw_envelope (HEADER *msg, char *fcc)
- {
-+ draw_sidebar (MENU_COMPOSE);
- draw_envelope_addr (HDR_FROM, msg->env->from);
- draw_envelope_addr (HDR_TO, msg->env->to);
- draw_envelope_addr (HDR_CC, msg->env->cc);
diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-delimnullwide.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-delimnullwide.patch
deleted file mode 100644
index 11d2ced5a0c..00000000000
--- a/pkgs/applications/networking/mailreaders/mutt/sidebar-delimnullwide.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From: Evgeni Golov
-Date: Wed, 5 Mar 2014 17:46:07 +0100
-Subject: sidebar-delimnullwide
-
-SidebarDelim can be NULL and strlen(NULL) is a bad idea, as it will segfault.
-Wrap it with NONULL().
-
-While at it, change strlen to mbstowcs for better utf8 support.
-
-Closes: #696145, #663883
-
-Gbp-Pq: Topic mutt-patched
----
- sidebar.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/sidebar.c b/sidebar.c
-index 51a25ca..c3ea338 100644
---- a/sidebar.c
-+++ b/sidebar.c
-@@ -88,7 +88,7 @@ char *make_sidebar_entry(char *box, int size, int new, int flagged)
- int box_len, box_bytes;
- int int_len;
- int right_offset = 0;
-- int delim_len = strlen(SidebarDelim);
-+ int delim_len = mbstowcs(NULL, NONULL(SidebarDelim), 0);
- static char *entry;
-
- right_width = left_width = 0;
-@@ -178,7 +178,7 @@ int draw_sidebar(int menu) {
- #ifndef USE_SLANG_CURSES
- attr_t attrs;
- #endif
-- short delim_len = strlen(SidebarDelim);
-+ short delim_len = mbstowcs(NULL, NONULL(SidebarDelim), 0);
- short color_pair;
-
- static bool initialized = false;
diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-dotpathsep.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-dotpathsep.patch
deleted file mode 100644
index 315fa1649bc..00000000000
--- a/pkgs/applications/networking/mailreaders/mutt/sidebar-dotpathsep.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-From: Fabian Groffen
-Date: Tue, 4 Mar 2014 21:12:15 +0100
-Subject: sidebar-dotpathsep
-
-Make path separators for sidebar folders configurable.
-
-When using IMAP, a '.' is often used as path separator, hence make the
-path separators configurable through sidebar_delim_chars variable.
-It defaults to "/." to work for both mboxes as well as IMAP folders. It
-can be set to only "/" or "." or whichever character desired as needed.
-
-Gbp-Pq: Topic mutt-patched
----
- globals.h | 1 +
- init.h | 8 ++++++++
- sidebar.c | 31 ++++++++++++++++++++++++-------
- 3 files changed, 33 insertions(+), 7 deletions(-)
-
-diff --git a/globals.h b/globals.h
-index 004c795..602f932 100644
---- a/globals.h
-+++ b/globals.h
-@@ -119,6 +119,7 @@ WHERE char *SendCharset;
- WHERE char *Sendmail;
- WHERE char *Shell;
- WHERE char *SidebarDelim;
-+WHERE char *SidebarDelimChars INITVAL (NULL);
- WHERE char *Signature;
- WHERE char *SimpleSearch;
- #if USE_SMTP
-diff --git a/init.h b/init.h
-index c664e5f..166671b 100644
---- a/init.h
-+++ b/init.h
-@@ -2051,6 +2051,14 @@ struct option_t MuttVars[] = {
- ** .pp
- ** The width of the sidebar.
- */
-+ { "sidebar_delim_chars", DT_STR, R_NONE, UL &SidebarDelimChars, UL "/." },
-+ /*
-+ ** .pp
-+ ** This contains the list of characters which you would like to treat
-+ ** as folder separators for displaying paths in the sidebar. If
-+ ** you're not using IMAP folders, you probably prefer setting this to "/"
-+ ** alone.
-+ */
- { "pgp_use_gpg_agent", DT_BOOL, R_NONE, OPTUSEGPGAGENT, 0},
- /*
- ** .pp
-diff --git a/sidebar.c b/sidebar.c
-index 6098c2a..4356ffc 100644
---- a/sidebar.c
-+++ b/sidebar.c
-@@ -249,20 +249,37 @@ int draw_sidebar(int menu) {
- // calculate depth of current folder and generate its display name with indented spaces
- int sidebar_folder_depth = 0;
- char *sidebar_folder_name;
-- sidebar_folder_name = basename(tmp->path);
-+ int i;
-+ sidebar_folder_name = tmp->path;
-+ /* disregard a trailing separator, so strlen() - 2
-+ * https://bugs.gentoo.org/show_bug.cgi?id=373197#c16 */
-+ for (i = strlen(sidebar_folder_name) - 2; i >= 0; i--) {
-+ if (SidebarDelimChars &&
-+ strchr(SidebarDelimChars, sidebar_folder_name[i]))
-+ {
-+ sidebar_folder_name += i + 1;
-+ break;
-+ }
-+ }
- if ( maildir_is_prefix ) {
- char *tmp_folder_name;
-- int i;
-+ int lastsep = 0;
- tmp_folder_name = tmp->path + strlen(Maildir);
-- for (i = 0; i < strlen(tmp->path) - strlen(Maildir); i++) {
-- if (tmp_folder_name[i] == '/') sidebar_folder_depth++;
-- }
-+ for (i = 0; i < strlen(tmp_folder_name) - 1; i++) {
-+ if (SidebarDelimChars &&
-+ strchr(SidebarDelimChars, tmp_folder_name[i]))
-+ {
-+ sidebar_folder_depth++;
-+ lastsep = i + 1;
-+ }
-+ }
- if (sidebar_folder_depth > 0) {
-- sidebar_folder_name = malloc(strlen(basename(tmp->path)) + sidebar_folder_depth + 1);
-+ tmp_folder_name += lastsep; /* basename */
-+ sidebar_folder_name = malloc(strlen(tmp_folder_name) + sidebar_folder_depth + 1);
- for (i=0; i < sidebar_folder_depth; i++)
- sidebar_folder_name[i]=' ';
- sidebar_folder_name[i]=0;
-- strncat(sidebar_folder_name, basename(tmp->path), strlen(basename(tmp->path)) + sidebar_folder_depth);
-+ strncat(sidebar_folder_name, tmp_folder_name, strlen(tmp_folder_name) + sidebar_folder_depth);
- }
- }
- printw( "%.*s", SidebarWidth - delim_len + 1,
diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-new.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-new.patch
deleted file mode 100644
index fb265346361..00000000000
--- a/pkgs/applications/networking/mailreaders/mutt/sidebar-new.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-From 355399bde98203af59d20821f9e840fc056bd383 Mon Sep 17 00:00:00 2001
-From: Julius Haertl
-Date: Tue, 9 Sep 2014 22:31:49 +0200
-Subject: Patch for sidebar iteration functionality
-
-sidebar-new will move the selected folder to the next with new messages.
-If the end is reached, it will start at the top.
-
-Useful macros would be:
-
- macro index a ""
- macro pager a ""
----
- OPS | 1 +
- curs_main.c | 1 +
- functions.h | 2 ++
- pager.c | 1 +
- sidebar.c | 10 ++++++++++
- 5 files changed, 15 insertions(+)
-
-diff --git a/OPS b/OPS
-index 1ed9c96..3ffb82a 100644
---- a/OPS
-+++ b/OPS
-@@ -187,3 +187,4 @@ OP_SIDEBAR_PREV "go to previous mailbox"
- OP_SIDEBAR_OPEN "open hilighted mailbox"
- OP_SIDEBAR_NEXT_NEW "go down to next mailbox with new mail"
- OP_SIDEBAR_PREV_NEW "go to previous mailbox with new mail"
-+OP_SIDEBAR_NEW "iterate though mailboxes with new mail"
-diff --git a/curs_main.c b/curs_main.c
-index acb106d..2e35f90 100644
---- a/curs_main.c
-+++ b/curs_main.c
-@@ -2328,6 +2328,7 @@ int mutt_index_menu (void)
- case OP_SIDEBAR_PREV:
- case OP_SIDEBAR_NEXT_NEW:
- case OP_SIDEBAR_PREV_NEW:
-+ case OP_SIDEBAR_NEW:
- scroll_sidebar(op, menu->menu);
- break;
- default:
-diff --git a/functions.h b/functions.h
-index 363b4d5..1485080 100644
---- a/functions.h
-+++ b/functions.h
-@@ -176,6 +176,7 @@ const struct binding_t OpMain[] = { /* map: index */
- { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
- { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL},
- { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL},
-+ { "sidebar-new", OP_SIDEBAR_NEW, NULL },
- { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
- { NULL, 0, NULL }
- };
-@@ -287,6 +288,7 @@ const struct binding_t OpPager[] = { /* map: pager */
- { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
- { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL},
- { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL},
-+ { "sidebar-new", OP_SIDEBAR_NEW, NULL },
- { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
- { NULL, 0, NULL }
- };
-diff --git a/pager.c b/pager.c
-index 8d64fe1..696e55c 100644
---- a/pager.c
-+++ b/pager.c
-@@ -2791,6 +2791,7 @@ search_next:
- case OP_SIDEBAR_PREV:
- case OP_SIDEBAR_NEXT_NEW:
- case OP_SIDEBAR_PREV_NEW:
-+ case OP_SIDEBAR_NEW:
- scroll_sidebar(ch, MENU_PAGER);
- break;
-
-diff --git a/sidebar.c b/sidebar.c
-index c3ea338..eb8ecd2 100644
---- a/sidebar.c
-+++ b/sidebar.c
-@@ -429,6 +429,16 @@ void scroll_sidebar(int op, int menu)
- CurBuffy = CurBuffy->next;
- }
- break;
-+ case OP_SIDEBAR_NEW:
-+ if ( (tmp = exist_next_new()) == NULL)
-+ tmp = TopBuffy;
-+ if ( tmp->msg_unread == 0 ) {
-+ CurBuffy = tmp;
-+ tmp = exist_next_new();
-+ }
-+ if ( tmp != NULL )
-+ CurBuffy = tmp;
-+ break;
- default:
- return;
- }
---
-2.6.0.rc0.2.g7662973.dirty
-
diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-newonly.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-newonly.patch
deleted file mode 100644
index d206848026b..00000000000
--- a/pkgs/applications/networking/mailreaders/mutt/sidebar-newonly.patch
+++ /dev/null
@@ -1,198 +0,0 @@
-From: Steve Kemp
-Date: Tue, 4 Mar 2014 22:07:06 +0100
-Subject: sidebar-newonly
-
-patches written by Steve Kemp, it adds two new functionalities to the sidebar,
-so only the mailbox with new messages will be shown (and/or) selected
-See Debian bug http://bugs.debian.org/532510
-
-Gbp-Pq: Topic mutt-patched
----
- OPS | 2 ++
- curs_main.c | 2 ++
- functions.h | 4 ++++
- init.h | 5 +++++
- mutt.h | 2 ++
- pager.c | 2 ++
- sidebar.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
- 7 files changed, 70 insertions(+), 2 deletions(-)
-
-diff --git a/OPS b/OPS
-index b036db9..1ed9c96 100644
---- a/OPS
-+++ b/OPS
-@@ -185,3 +185,5 @@ OP_SIDEBAR_SCROLL_DOWN "scroll the mailbox pane down 1 page"
- OP_SIDEBAR_NEXT "go down to next mailbox"
- OP_SIDEBAR_PREV "go to previous mailbox"
- OP_SIDEBAR_OPEN "open hilighted mailbox"
-+OP_SIDEBAR_NEXT_NEW "go down to next mailbox with new mail"
-+OP_SIDEBAR_PREV_NEW "go to previous mailbox with new mail"
-diff --git a/curs_main.c b/curs_main.c
-index ea530a6..acb106d 100644
---- a/curs_main.c
-+++ b/curs_main.c
-@@ -2326,6 +2326,8 @@ int mutt_index_menu (void)
- case OP_SIDEBAR_SCROLL_DOWN:
- case OP_SIDEBAR_NEXT:
- case OP_SIDEBAR_PREV:
-+ case OP_SIDEBAR_NEXT_NEW:
-+ case OP_SIDEBAR_PREV_NEW:
- scroll_sidebar(op, menu->menu);
- break;
- default:
-diff --git a/functions.h b/functions.h
-index ef8937a..363b4d5 100644
---- a/functions.h
-+++ b/functions.h
-@@ -174,6 +174,8 @@ const struct binding_t OpMain[] = { /* map: index */
- { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL },
- { "sidebar-next", OP_SIDEBAR_NEXT, NULL },
- { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
-+ { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL},
-+ { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL},
- { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
- { NULL, 0, NULL }
- };
-@@ -283,6 +285,8 @@ const struct binding_t OpPager[] = { /* map: pager */
- { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL },
- { "sidebar-next", OP_SIDEBAR_NEXT, NULL },
- { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
-+ { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL},
-+ { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL},
- { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
- { NULL, 0, NULL }
- };
-diff --git a/init.h b/init.h
-index 166671b..a5d4238 100644
---- a/init.h
-+++ b/init.h
-@@ -2059,6 +2059,11 @@ struct option_t MuttVars[] = {
- ** you're not using IMAP folders, you probably prefer setting this to "/"
- ** alone.
- */
-+ {"sidebar_newmail_only", DT_BOOL, R_BOTH, OPTSIDEBARNEWMAILONLY, 0 },
-+ /*
-+ ** .pp
-+ ** Show only new mail in the sidebar.
-+ */
- { "pgp_use_gpg_agent", DT_BOOL, R_NONE, OPTUSEGPGAGENT, 0},
- /*
- ** .pp
-diff --git a/mutt.h b/mutt.h
-index 5f25406..d73e514 100644
---- a/mutt.h
-+++ b/mutt.h
-@@ -529,6 +529,8 @@ enum
- OPTDONTHANDLEPGPKEYS, /* (pseudo) used to extract PGP keys */
- OPTUNBUFFEREDINPUT, /* (pseudo) don't use key buffer */
-
-+ OPTSIDEBARNEWMAILONLY,
-+
- OPTMAX
- };
-
-diff --git a/pager.c b/pager.c
-index 5cfcb75..8d64fe1 100644
---- a/pager.c
-+++ b/pager.c
-@@ -2789,6 +2789,8 @@ search_next:
- case OP_SIDEBAR_SCROLL_DOWN:
- case OP_SIDEBAR_NEXT:
- case OP_SIDEBAR_PREV:
-+ case OP_SIDEBAR_NEXT_NEW:
-+ case OP_SIDEBAR_PREV_NEW:
- scroll_sidebar(ch, MENU_PAGER);
- break;
-
-diff --git a/sidebar.c b/sidebar.c
-index 8f58f85..51a25ca 100644
---- a/sidebar.c
-+++ b/sidebar.c
-@@ -269,8 +269,21 @@ int draw_sidebar(int menu) {
- SETCOLOR(MT_COLOR_NEW);
- else if ( tmp->msg_flagged > 0 )
- SETCOLOR(MT_COLOR_FLAGGED);
-- else
-- SETCOLOR(MT_COLOR_NORMAL);
-+ else {
-+ /* make sure the path is either:
-+ 1. Containing new mail.
-+ 2. The inbox.
-+ 3. The current box.
-+ */
-+ if ((option (OPTSIDEBARNEWMAILONLY)) &&
-+ ( (tmp->msg_unread <= 0) &&
-+ ( tmp != Incoming ) &&
-+ Context &&
-+ ( strcmp( tmp->path, Context->path ) != 0 ) ) )
-+ continue;
-+ else
-+ SETCOLOR(MT_COLOR_NORMAL);
-+ }
-
- move( lines, 0 );
- if ( Context && !strcmp( tmp->path, Context->path ) ) {
-@@ -336,6 +349,29 @@ int draw_sidebar(int menu) {
- return 0;
- }
-
-+BUFFY * exist_next_new()
-+{
-+ BUFFY *tmp = CurBuffy;
-+ if(tmp == NULL) return NULL;
-+ while (tmp->next != NULL)
-+ {
-+ tmp = tmp->next;
-+ if(tmp->msg_unread) return tmp;
-+ }
-+ return NULL;
-+}
-+
-+BUFFY * exist_prev_new()
-+{
-+ BUFFY *tmp = CurBuffy;
-+ if(tmp == NULL) return NULL;
-+ while (tmp->prev != NULL)
-+ {
-+ tmp = tmp->prev;
-+ if(tmp->msg_unread) return tmp;
-+ }
-+ return NULL;
-+}
-
- void set_buffystats(CONTEXT* Context)
- {
-@@ -352,18 +388,33 @@ void set_buffystats(CONTEXT* Context)
-
- void scroll_sidebar(int op, int menu)
- {
-+ BUFFY *tmp;
- if(!SidebarWidth) return;
- if(!CurBuffy) return;
-
- switch (op) {
- case OP_SIDEBAR_NEXT:
-+ if (!option (OPTSIDEBARNEWMAILONLY)) {
- if ( CurBuffy->next == NULL ) return;
- CurBuffy = CurBuffy->next;
- break;
-+ }
-+ case OP_SIDEBAR_NEXT_NEW:
-+ if ( (tmp = exist_next_new()) == NULL)
-+ return;
-+ else CurBuffy = tmp;
-+ break;
- case OP_SIDEBAR_PREV:
-+ if (!option (OPTSIDEBARNEWMAILONLY)) {
- if ( CurBuffy->prev == NULL ) return;
- CurBuffy = CurBuffy->prev;
- break;
-+ }
-+ case OP_SIDEBAR_PREV_NEW:
-+ if ( (tmp = exist_prev_new()) == NULL)
-+ return;
-+ else CurBuffy = tmp;
-+ break;
- case OP_SIDEBAR_SCROLL_UP:
- CurBuffy = TopBuffy;
- if ( CurBuffy != Incoming ) {
diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar-utf8.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar-utf8.patch
deleted file mode 100644
index d67e43c24b6..00000000000
--- a/pkgs/applications/networking/mailreaders/mutt/sidebar-utf8.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-From: Antonio Radici
-Date: Tue, 4 Mar 2014 15:39:14 +0100
-Subject: sidebar-utf8
-
-This patch fixes a problem with utf-8 strings and the sidebar,
-it rewrites entirely make_sidebar_entry so it also fixes some
-segfaults due to misallocations and overflows.
-
-See:
- http://bugs.debian.org/584581
- http://bugs.debian.org/603287
-
-Gbp-Pq: Topic mutt-patched
----
- sidebar.c | 97 +++++++++++++++++++++++++++++++++++++++++++--------------------
- 1 file changed, 67 insertions(+), 30 deletions(-)
-
-diff --git a/sidebar.c b/sidebar.c
-index 4356ffc..8f58f85 100644
---- a/sidebar.c
-+++ b/sidebar.c
-@@ -30,6 +30,7 @@
- #include
- #include "keymap.h"
- #include
-+#include
-
- /*BUFFY *CurBuffy = 0;*/
- static BUFFY *TopBuffy = 0;
-@@ -82,36 +83,72 @@ void calc_boundaries (int menu)
-
- char *make_sidebar_entry(char *box, int size, int new, int flagged)
- {
-- static char *entry = 0;
-- char *c;
-- int i = 0;
-- int delim_len = strlen(SidebarDelim);
--
-- c = realloc(entry, SidebarWidth - delim_len + 2);
-- if ( c ) entry = c;
-- entry[SidebarWidth - delim_len + 1] = 0;
-- for (; i < SidebarWidth - delim_len + 1; entry[i++] = ' ' );
-- i = strlen(box);
-- strncpy( entry, box, i < (SidebarWidth - delim_len + 1) ? i : (SidebarWidth - delim_len + 1) );
--
-- if (size == -1)
-- sprintf(entry + SidebarWidth - delim_len - 3, "?");
-- else if ( new ) {
-- if (flagged > 0) {
-- sprintf(
-- entry + SidebarWidth - delim_len - 5 - quick_log10(size) - quick_log10(new) - quick_log10(flagged),
-- "% d(%d)[%d]", size, new, flagged);
-- } else {
-- sprintf(
-- entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(new),
-- "% d(%d)", size, new);
-- }
-- } else if (flagged > 0) {
-- sprintf( entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(flagged), "% d[%d]", size, flagged);
-- } else {
-- sprintf( entry + SidebarWidth - delim_len - 1 - quick_log10(size), "% d", size);
-- }
-- return entry;
-+ char int_store[20]; // up to 64 bits integers
-+ int right_width, left_width;
-+ int box_len, box_bytes;
-+ int int_len;
-+ int right_offset = 0;
-+ int delim_len = strlen(SidebarDelim);
-+ static char *entry;
-+
-+ right_width = left_width = 0;
-+ box_len = box_bytes = 0;
-+
-+ // allocate an entry big enough to contain SidebarWidth wide chars
-+ entry = malloc((SidebarWidth*4)+1); // TODO: error check
-+
-+ // determine the right space (i.e.: how big are the numbers that we want to print)
-+ if ( size > 0 ) {
-+ int_len = snprintf(int_store, sizeof(int_store), "%d", size);
-+ right_width += int_len;
-+ } else {
-+ right_width = 1; // to represent 0
-+ }
-+ if ( new > 0 ) {
-+ int_len = snprintf(int_store, sizeof(int_store), "%d", new);
-+ right_width += int_len + 2; // 2 is for ()
-+ }
-+ if ( flagged > 0 ) {
-+ int_len = snprintf(int_store, sizeof(int_store), "%d", flagged);
-+ right_width += int_len + 2; // 2 is for []
-+ }
-+
-+ // determine how much space we have for *box and its padding (if any)
-+ left_width = SidebarWidth - right_width - 1 - delim_len; // 1 is for the space
-+ //fprintf(stdout, "left_width: %d right_width: %d\n", left_width, right_width);
-+ // right side overflow case
-+ if ( left_width <= 0 ) {
-+ snprintf(entry, SidebarWidth*4, "%-*.*s ...", SidebarWidth-4-delim_len, SidebarWidth-4-delim_len, box);
-+ return entry;
-+ }
-+ right_width -= delim_len;
-+
-+ // to support utf-8 chars we need to add enough space padding in case there
-+ // are less chars than bytes in *box
-+ box_len = mbstowcs(NULL, box, 0);
-+ box_bytes = strlen(box);
-+ // debug
-+ //fprintf(stdout, "box_len: %d box_bytes: %d (diff: %d)\n", box_len, box_bytes, (box_bytes-box_len));
-+ // if there is less string than the space we allow, then we will add the
-+ // spaces
-+ if ( box_len != -1 && box_len < left_width ) {
-+ left_width += (box_bytes - box_len);
-+ }
-+ // otherwise sprintf will truncate the string for us (therefore, no else case)
-+
-+ // print the sidebar entry (without new and flagged messages, at the moment)
-+ //fprintf(stdout, "left_width: %d right_width: %d\n", left_width, right_width);
-+ right_offset = snprintf(entry, SidebarWidth*4, "%-*.*s %d", left_width, left_width, box, size);
-+
-+ // then pad new and flagged messages if any
-+ if ( new > 0 ) {
-+ right_offset += snprintf(entry+right_offset, SidebarWidth*4-right_offset, "(%d)", new);
-+ }
-+ if ( flagged > 0 ) {
-+ right_offset += snprintf(entry+right_offset, SidebarWidth*4-right_offset, "[%d]", flagged);
-+ }
-+
-+ return entry;
- }
-
- void set_curbuffy(char buf[LONG_STRING])
diff --git a/pkgs/applications/networking/mailreaders/mutt/sidebar.patch b/pkgs/applications/networking/mailreaders/mutt/sidebar.patch
index bac1b4ab83b..218de7a0c46 100644
--- a/pkgs/applications/networking/mailreaders/mutt/sidebar.patch
+++ b/pkgs/applications/networking/mailreaders/mutt/sidebar.patch
@@ -1,306 +1,373 @@
-From: Antonio Radici
-Date: Tue, 4 Mar 2014 15:21:10 +0100
-Subject: sidebar
-
-When enabled, mutt will show a list of mailboxes with (new) message counts in a
-separate column on the left side of the screen.
-
-As this feature is still considered to be unstable, this patch is only applied
-in the "mutt-patched" package.
-
-* Configuration variables:
-
- sidebar_delim (string, default "|")
-
- This specifies the delimiter between the sidebar (if visible) and
- other screens.
-
- sidebar_visible (boolean, default no)
-
- This specifies whether or not to show sidebar (left-side list of folders).
-
- sidebar_width (integer, default 0)
--
- The width of the sidebar.
-
-* Patch source:
- - http://www.lunar-linux.org/index.php?page=mutt-sidebar
- - http://lunar-linux.org/~tchan/mutt/patch-1.5.19.sidebar.20090522.txt
-
-* Changes made:
- - 2008-08-02 myon: Refreshed patch using quilt push -f to remove hunks we do
- not need (Makefile.in).
-
- - 2014-03-04 evgeni: refresh sidebar patch with the version from OpenBSD
- Source:
- ftp://ftp.openbsd.org/pub/OpenBSD/distfiles/mutt/sidebar-1.5.22.diff1.gz
-
-Signed-off-by: Matteo F. Vescovi
-Signed-off-by: Evgeni Golov
-
-Gbp-Pq: Topic mutt-patched
----
- Makefile.am | 1 +
- OPS | 5 +
- buffy.c | 124 +++++++++++++++++++++
- buffy.h | 4 +
- color.c | 2 +
- compose.c | 26 ++---
- curs_main.c | 30 +++++-
- flags.c | 3 +
- functions.h | 10 ++
- globals.h | 4 +
- imap/command.c | 7 ++
- imap/imap.c | 2 +-
- init.h | 21 ++++
- mailbox.h | 1 +
- mbox.c | 2 +
- menu.c | 20 ++--
- mh.c | 22 ++++
- mutt.h | 4 +
- mutt_curses.h | 3 +
- muttlib.c | 48 +++++++++
- mx.c | 15 +++
- mx.h | 1 +
- pager.c | 30 ++++--
- sidebar.c | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- sidebar.h | 36 +++++++
- 25 files changed, 720 insertions(+), 34 deletions(-)
- create mode 100644 sidebar.c
- create mode 100644 sidebar.h
-
-diff --git a/Makefile.am b/Makefile.am
-index 5dfeff6..cf1ac98 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -33,6 +33,7 @@ mutt_SOURCES = \
- rfc822.c rfc1524.c rfc2047.c rfc2231.c rfc3676.c \
- score.c send.c sendlib.c signal.c sort.c \
- status.c system.c thread.c charset.c history.c lib.c \
-+ sidebar.c \
- muttlib.c editmsg.c mbyte.c mutt_idna.c \
- url.c ascii.c crypt-mod.c crypt-mod.h safe_asprintf.c
+diff -urN mutt-1.6.1/buffy.c mutt-1.6.1-sidebar/buffy.c
+--- mutt-1.6.1/buffy.c 2016-06-12 18:43:00.397447512 +0100
++++ mutt-1.6.1-sidebar/buffy.c 2016-06-12 18:43:03.951502935 +0100
+@@ -27,6 +27,10 @@
-diff --git a/OPS b/OPS
-index 02cea8e..b036db9 100644
---- a/OPS
-+++ b/OPS
-@@ -180,3 +180,8 @@ OP_WHAT_KEY "display the keycode for a key press"
- OP_MAIN_SHOW_LIMIT "show currently active limit pattern"
- OP_MAIN_COLLAPSE_THREAD "collapse/uncollapse current thread"
- OP_MAIN_COLLAPSE_ALL "collapse/uncollapse all threads"
-+OP_SIDEBAR_SCROLL_UP "scroll the mailbox pane up 1 page"
-+OP_SIDEBAR_SCROLL_DOWN "scroll the mailbox pane down 1 page"
-+OP_SIDEBAR_NEXT "go down to next mailbox"
-+OP_SIDEBAR_PREV "go to previous mailbox"
-+OP_SIDEBAR_OPEN "open hilighted mailbox"
-diff --git a/buffy.c b/buffy.c
-index 12a16d1..90ca6db 100644
---- a/buffy.c
-+++ b/buffy.c
-@@ -161,6 +161,49 @@ void mutt_buffy_cleanup (const char *buf, struct stat *st)
- }
- }
+ #include "mutt_curses.h"
-+static int buffy_compare_name(const void *a, const void *b) {
-+ const BUFFY *b1 = * (BUFFY * const *) a;
-+ const BUFFY *b2 = * (BUFFY * const *) b;
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
+
-+ return mutt_strcoll(b1->path, b2->path);
-+}
-+
-+static BUFFY *buffy_sort(BUFFY *b)
-+{
-+ BUFFY *tmp = b;
-+ int buffycount = 0;
-+ BUFFY **ary;
-+ int i;
-+
-+ if (!option(OPTSIDEBARSORT))
-+ return b;
-+
-+ for (; tmp != NULL; tmp = tmp->next)
-+ buffycount++;
-+
-+ ary = (BUFFY **) safe_calloc(buffycount, sizeof (*ary));
-+
-+ tmp = b;
-+ for (i = 0; tmp != NULL; tmp = tmp->next, i++) {
-+ ary[i] = tmp;
-+ }
-+
-+ qsort(ary, buffycount, sizeof(*ary), buffy_compare_name);
-+
-+ for (i = 0; i < buffycount - 1; i++) {
-+ ary[i]->next = ary[i+1];
-+ }
-+ ary[buffycount - 1]->next = NULL;
-+ for (i = 1; i < buffycount; i++) {
-+ ary[i]->prev = ary[i-1];
-+ }
-+ ary[0]->prev = NULL;
-+
-+ tmp = ary[0];
-+ free(ary);
-+ return tmp;
-+}
-+
- BUFFY *mutt_find_mailbox (const char *path)
+ #ifdef USE_IMAP
+ #include "imap.h"
+ #endif
+@@ -196,9 +200,17 @@
+ static BUFFY *buffy_new (const char *path)
{
- BUFFY *tmp = NULL;
-@@ -282,6 +325,7 @@ int mutt_parse_mailboxes (BUFFER *path, BUFFER *s, unsigned long data, BUFFER *e
- else
- (*tmp)->size = 0;
+ BUFFY* buffy;
++#ifdef USE_SIDEBAR
++ char rp[PATH_MAX] = "";
++ char *r = NULL;
++#endif
+
+ buffy = (BUFFY *) safe_calloc (1, sizeof (BUFFY));
+ strfcpy (buffy->path, path, sizeof (buffy->path));
++#ifdef USE_SIDEBAR
++ r = realpath (path, rp);
++ strfcpy (buffy->realpath, r ? rp : path, sizeof (buffy->realpath));
++#endif
+ buffy->next = NULL;
+ buffy->magic = 0;
+
+@@ -215,7 +227,10 @@
+ BUFFY **tmp,*tmp1;
+ char buf[_POSIX_PATH_MAX];
+ struct stat sb;
+- char f1[PATH_MAX], f2[PATH_MAX];
++ char f1[PATH_MAX];
++#ifndef USE_SIDEBAR
++ char f2[PATH_MAX];
++#endif
+ char *p, *q;
+
+ while (MoreArgs (s))
+@@ -228,6 +243,9 @@
+ for (tmp = &Incoming; *tmp;)
+ {
+ tmp1=(*tmp)->next;
++#ifdef USE_SIDEBAR
++ mutt_sb_notify_mailbox (*tmp, 0);
++#endif
+ buffy_free (tmp);
+ *tmp=tmp1;
+ }
+@@ -243,8 +261,13 @@
+ p = realpath (buf, f1);
+ for (tmp = &Incoming; *tmp; tmp = &((*tmp)->next))
+ {
++#ifdef USE_SIDEBAR
++ q = (*tmp)->realpath;
++ if (mutt_strcmp (p ? p : buf, q) == 0)
++#else
+ q = realpath ((*tmp)->path, f2);
+ if (mutt_strcmp (p ? p : buf, q ? q : (*tmp)->path) == 0)
++#endif
+ {
+ dprint(3,(debugfile,"mailbox '%s' already registered as '%s'\n", buf, (*tmp)->path));
+ break;
+@@ -256,14 +279,21 @@
+ if(*tmp)
+ {
+ tmp1=(*tmp)->next;
++#ifdef USE_SIDEBAR
++ mutt_sb_notify_mailbox (*tmp, 0);
++#endif
+ buffy_free (tmp);
+ *tmp=tmp1;
+ }
+ continue;
+ }
+
+- if (!*tmp)
++ if (!*tmp) {
+ *tmp = buffy_new (buf);
++#ifdef USE_SIDEBAR
++ mutt_sb_notify_mailbox (*tmp, 1);
++#endif
++ }
+
+ (*tmp)->new = 0;
+ (*tmp)->notified = 1;
+@@ -306,6 +336,13 @@
+ return 0;
}
-+ Incoming = buffy_sort(Incoming);
- return 0;
- }
-@@ -357,6 +401,69 @@ static int buffy_maildir_hasnew (BUFFY* mailbox)
++#ifdef USE_SIDEBAR
++ if (option (OPTSIDEBAR) && mailbox->msg_unread > 0) {
++ mailbox->new = 1;
++ return 1;
++ }
++#endif
++
+ if ((dirp = opendir (path)) == NULL)
+ {
+ mailbox->magic = 0;
+@@ -357,6 +394,93 @@
return 0;
}
+
-+/* update message counts for the sidebar */
-+void buffy_maildir_update (BUFFY* mailbox)
++#ifdef USE_SIDEBAR
++/**
++ * buffy_maildir_update_dir - Update counts for one directory
++ * @mailbox: BUFFY representing a maildir mailbox
++ * @dir: Which directory to search
++ *
++ * Look through one directory of a maildir mailbox. The directory could
++ * be either "new" or "cur".
++ *
++ * Count how many new, or flagged, messages there are.
++ */
++static void
++buffy_maildir_update_dir (BUFFY *mailbox, const char *dir)
+{
-+ char path[_POSIX_PATH_MAX];
-+ DIR *dirp;
-+ struct dirent *de;
-+ char *p;
++ char path[_POSIX_PATH_MAX] = "";
++ DIR *dirp = NULL;
++ struct dirent *de = NULL;
++ char *p = NULL;
++ int read;
+
-+ mailbox->msgcount = 0;
-+ mailbox->msg_unread = 0;
-+ mailbox->msg_flagged = 0;
++ snprintf (path, sizeof (path), "%s/%s", mailbox->path, dir);
+
-+ snprintf (path, sizeof (path), "%s/new", mailbox->path);
-+
-+ if ((dirp = opendir (path)) == NULL)
-+ {
++ dirp = opendir (path);
++ if (!dirp)
++ {
+ mailbox->magic = 0;
+ return;
-+ }
-+
++ }
++
+ while ((de = readdir (dirp)) != NULL)
+ {
+ if (*de->d_name == '.')
+ continue;
+
-+ if (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T')) {
-+ mailbox->new = 1;
-+ mailbox->msgcount++;
++ /* Matches maildir_parse_flags logic */
++ read = 0;
++ mailbox->msg_count++;
++ p = strstr (de->d_name, ":2,");
++ if (p)
++ {
++ p += 3;
++ if (strchr (p, 'S'))
++ read = 1;
++ if (strchr (p, 'F'))
++ mailbox->msg_flagged++;
++ }
++ if (!read) {
+ mailbox->msg_unread++;
+ }
+ }
+
+ closedir (dirp);
-+ snprintf (path, sizeof (path), "%s/cur", mailbox->path);
-+
-+ if ((dirp = opendir (path)) == NULL)
-+ {
-+ mailbox->magic = 0;
-+ return;
-+ }
-+
-+ while ((de = readdir (dirp)) != NULL)
-+ {
-+ if (*de->d_name == '.')
-+ continue;
-+
-+ if (!(p = strstr (de->d_name, ":2,")) || !strchr (p + 3, 'T')) {
-+ mailbox->msgcount++;
-+ if ((p = strstr (de->d_name, ":2,"))) {
-+ if (!strchr (p + 3, 'T')) {
-+ if (!strchr (p + 3, 'S'))
-+ mailbox->msg_unread++;
-+ if (strchr(p + 3, 'F'))
-+ mailbox->msg_flagged++;
-+ }
-+ }
-+ }
-+ }
-+
-+ closedir (dirp);
+}
++
++/**
++ * buffy_maildir_update - Update messages counts for a maildir mailbox
++ * @mailbox: BUFFY representing a maildir mailbox
++ *
++ * Open a mailbox directories and update our record of how many new, or
++ * flagged, messages there are.
++ */
++void
++buffy_maildir_update (BUFFY *mailbox)
++{
++ if (!option (OPTSIDEBAR))
++ return;
++
++ mailbox->msg_count = 0;
++ mailbox->msg_unread = 0;
++ mailbox->msg_flagged = 0;
++
++ buffy_maildir_update_dir (mailbox, "new");
++ if (mailbox->msg_count) {
++ mailbox->new = 1;
++ }
++ buffy_maildir_update_dir (mailbox, "cur");
++
++ mailbox->sb_last_checked = time (NULL);
++
++ /* make sure the updates are actually put on screen */
++ if (SidebarWidth)
++ mutt_sb_draw();
++}
++
++#endif
+
/* returns 1 if mailbox has new mail */
static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb)
{
-@@ -388,6 +495,20 @@ static int buffy_mbox_hasnew (BUFFY* mailbox, struct stat *sb)
+@@ -368,7 +491,11 @@
+ else
+ statcheck = sb->st_mtime > sb->st_atime
+ || (mailbox->newly_created && sb->st_ctime == sb->st_mtime && sb->st_ctime == sb->st_atime);
++#ifdef USE_SIDEBAR
++ if ((!option (OPTSIDEBAR) && statcheck) || (option (OPTSIDEBAR) && mailbox->msg_unread > 0))
++#else
+ if (statcheck)
++#endif
+ {
+ if (!option(OPTMAILCHECKRECENT) || sb->st_mtime > mailbox->last_visited)
+ {
+@@ -388,6 +515,42 @@
return rc;
}
-+/* update message counts for the sidebar */
-+void buffy_mbox_update (BUFFY* mailbox)
++#ifdef USE_SIDEBAR
++/**
++ * buffy_mbox_update - Update messages counts for an mbox mailbox
++ * @mailbox: BUFFY representing an mbox mailbox
++ * @sb: stat(2) infomation about the mailbox file
++ *
++ * Open a mbox file and update our record of how many new, or flagged,
++ * messages there are. If the mailbox hasn't changed since the last call,
++ * the function does nothing.
++ */
++void
++buffy_mbox_update (BUFFY *mailbox, struct stat *sb)
+{
+ CONTEXT *ctx = NULL;
+
-+ ctx = mx_open_mailbox(mailbox->path, M_READONLY | M_QUIET | M_NOSORT | M_PEEK, NULL);
-+ if(ctx)
++ if (!option (OPTSIDEBAR))
++ return;
++ if ((mailbox->sb_last_checked > sb->st_mtime) && (mailbox->msg_count != 0))
++ return; /* no check necessary */
++
++ ctx = mx_open_mailbox (mailbox->path, M_READONLY | M_QUIET | M_NOSORT | M_PEEK, NULL);
++ if (ctx)
+ {
-+ mailbox->msgcount = ctx->msgcount;
-+ mailbox->msg_unread = ctx->unread;
-+ mx_close_mailbox(ctx, 0);
++ mailbox->msg_count = ctx->msgcount;
++ mailbox->msg_unread = ctx->unread;
++ mailbox->msg_flagged = ctx->flagged;
++ mailbox->sb_last_checked = time (NULL);
++ mx_close_mailbox (ctx, 0);
+ }
++
++ /* make sure the updates are actually put on screen */
++ if (SidebarWidth)
++ mutt_sb_draw();
+}
++#endif
+
int mutt_buffy_check (int force)
{
BUFFY *tmp;
-@@ -461,16 +582,19 @@ int mutt_buffy_check (int force)
+@@ -461,16 +623,25 @@
{
case M_MBOX:
case M_MMDF:
-+ buffy_mbox_update (tmp);
++#ifdef USE_SIDEBAR
++ buffy_mbox_update (tmp, &sb);
++#endif
if (buffy_mbox_hasnew (tmp, &sb) > 0)
BuffyCount++;
break;
case M_MAILDIR:
++#ifdef USE_SIDEBAR
+ buffy_maildir_update (tmp);
++#endif
if (buffy_maildir_hasnew (tmp) > 0)
BuffyCount++;
break;
case M_MH:
-+ mh_buffy_update (tmp->path, &tmp->msgcount, &tmp->msg_unread, &tmp->msg_flagged);
++#ifdef USE_SIDEBAR
++ mh_buffy_update (tmp);
++#endif
mh_buffy(tmp);
if (tmp->new)
BuffyCount++;
-diff --git a/buffy.h b/buffy.h
-index f9fc55a..672d178 100644
---- a/buffy.h
-+++ b/buffy.h
-@@ -25,7 +25,11 @@ typedef struct buffy_t
+diff -urN mutt-1.6.1/buffy.h mutt-1.6.1-sidebar/buffy.h
+--- mutt-1.6.1/buffy.h 2016-06-12 18:43:00.397447512 +0100
++++ mutt-1.6.1-sidebar/buffy.h 2016-06-12 18:43:03.951502935 +0100
+@@ -16,6 +16,9 @@
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
++#ifndef _BUFFY_H
++#define _BUFFY_H
++
+ /*parameter to mutt_parse_mailboxes*/
+ #define M_MAILBOXES 1
+ #define M_UNMAILBOXES 2
+@@ -23,13 +26,28 @@
+ typedef struct buffy_t
+ {
char path[_POSIX_PATH_MAX];
++#ifdef USE_SIDEBAR
++ char realpath[_POSIX_PATH_MAX];
++#endif
off_t size;
struct buffy_t *next;
++#ifdef USE_SIDEBAR
+ struct buffy_t *prev;
++#endif
short new; /* mailbox has new mail */
-+ int msgcount; /* total number of messages */
++#ifdef USE_SIDEBAR
++ int msg_count; /* total number of messages */
+ int msg_unread; /* number of unread messages */
+ int msg_flagged; /* number of flagged messages */
++ short is_hidden; /* is hidden from the sidebar */
++#endif
short notified; /* user has been notified */
short magic; /* mailbox type */
short newly_created; /* mbox or mmdf just popped into existence */
-diff --git a/color.c b/color.c
-index 64a46dc..d6f9198 100644
---- a/color.c
-+++ b/color.c
-@@ -94,6 +94,8 @@ static const struct mapping_t Fields[] =
+ time_t last_visited; /* time of last exit from this mailbox */
++#ifdef USE_SIDEBAR
++ time_t sb_last_checked; /* time of last buffy check from sidebar */
++#endif
+ }
+ BUFFY;
+
+@@ -49,3 +67,5 @@
+ void mutt_buffy_setnotified (const char *path);
+
+ void mh_buffy (BUFFY *);
++
++#endif /* _BUFFY_H */
+diff -urN mutt-1.6.1/color.c mutt-1.6.1-sidebar/color.c
+--- mutt-1.6.1/color.c 2016-06-12 18:43:00.397447512 +0100
++++ mutt-1.6.1-sidebar/color.c 2016-06-12 18:43:03.951502935 +0100
+@@ -94,6 +94,14 @@
{ "underline", MT_COLOR_UNDERLINE },
{ "index", MT_COLOR_INDEX },
{ "prompt", MT_COLOR_PROMPT },
-+ { "sidebar_new", MT_COLOR_NEW },
++#ifdef USE_SIDEBAR
++ { "sidebar_divider", MT_COLOR_DIVIDER },
+ { "sidebar_flagged", MT_COLOR_FLAGGED },
++ { "sidebar_highlight",MT_COLOR_HIGHLIGHT },
++ { "sidebar_indicator",MT_COLOR_SB_INDICATOR },
++ { "sidebar_new", MT_COLOR_NEW },
++ { "sidebar_spoolfile",MT_COLOR_SB_SPOOLFILE },
++#endif
{ NULL, 0 }
};
-diff --git a/compose.c b/compose.c
-index 9d87060..b63695f 100644
---- a/compose.c
-+++ b/compose.c
-@@ -72,7 +72,7 @@ enum
+@@ -146,6 +154,9 @@
+ ColorDefs[MT_COLOR_INDICATOR] = A_REVERSE;
+ ColorDefs[MT_COLOR_SEARCH] = A_REVERSE;
+ ColorDefs[MT_COLOR_MARKERS] = A_REVERSE;
++#ifdef USE_SIDEBAR
++ ColorDefs[MT_COLOR_HIGHLIGHT] = A_UNDERLINE;
++#endif
+ /* special meaning: toggle the relevant attribute */
+ ColorDefs[MT_COLOR_BOLD] = 0;
+ ColorDefs[MT_COLOR_UNDERLINE] = 0;
+diff -urN mutt-1.6.1/compose.c mutt-1.6.1-sidebar/compose.c
+--- mutt-1.6.1/compose.c 2016-06-12 18:43:00.398447528 +0100
++++ mutt-1.6.1-sidebar/compose.c 2016-06-12 18:43:03.952502951 +0100
+@@ -32,6 +32,9 @@
+ #include "mailbox.h"
+ #include "sort.h"
+ #include "charset.h"
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
+
+ #ifdef MIXMASTER
+ #include "remailer.h"
+@@ -72,7 +75,7 @@
#define HDR_XOFFSET 10
#define TITLE_FMT "%10s" /* Used for Prompts, which are ASCII */
@@ -309,16 +376,16 @@ index 9d87060..b63695f 100644
static const char * const Prompts[] =
{
-@@ -110,7 +110,7 @@ static void snd_entry (char *b, size_t blen, MUTTMENU *menu, int num)
+@@ -110,7 +113,7 @@
static void redraw_crypt_lines (HEADER *msg)
{
- mvaddstr (HDR_CRYPT, 0, "Security: ");
-+ mvaddstr (HDR_CRYPT, SidebarWidth, "Security: ");
++ mvprintw (HDR_CRYPT, SidebarWidth, TITLE_FMT, "Security: ");
if ((WithCrypto & (APPLICATION_PGP | APPLICATION_SMIME)) == 0)
{
-@@ -145,7 +145,7 @@ static void redraw_crypt_lines (HEADER *msg)
+@@ -145,16 +148,16 @@
addstr (_(" (OppEnc mode)"));
clrtoeol ();
@@ -327,7 +394,18 @@ index 9d87060..b63695f 100644
clrtoeol ();
if ((WithCrypto & APPLICATION_PGP)
-@@ -162,7 +162,7 @@ static void redraw_crypt_lines (HEADER *msg)
+ && (msg->security & APPLICATION_PGP) && (msg->security & SIGN))
+- printw ("%s%s", _(" sign as: "), PgpSignAs ? PgpSignAs : _(""));
++ printw (TITLE_FMT "%s", _("sign as: "), PgpSignAs ? PgpSignAs : _(""));
+
+ if ((WithCrypto & APPLICATION_SMIME)
+ && (msg->security & APPLICATION_SMIME) && (msg->security & SIGN)) {
+- printw ("%s%s", _(" sign as: "), SmimeDefaultKey ? SmimeDefaultKey : _(""));
++ printw (TITLE_FMT "%s", _("sign as: "), SmimeDefaultKey ? SmimeDefaultKey : _(""));
+ }
+
+ if ((WithCrypto & APPLICATION_SMIME)
+@@ -162,7 +165,7 @@
&& (msg->security & ENCRYPT)
&& SmimeCryptAlg
&& *SmimeCryptAlg) {
@@ -336,16 +414,17 @@ index 9d87060..b63695f 100644
NONULL(SmimeCryptAlg));
}
}
-@@ -175,7 +175,7 @@ static void redraw_mix_line (LIST *chain)
+@@ -175,7 +178,8 @@
int c;
char *t;
- mvaddstr (HDR_MIX, 0, " Mix: ");
-+ mvaddstr (HDR_MIX, SidebarWidth, " Mix: ");
++ /* L10N: "Mix" refers to the MixMaster chain for anonymous email */
++ mvprintw (HDR_MIX, SidebarWidth, TITLE_FMT, _("Mix: "));
if (!chain)
{
-@@ -190,7 +190,7 @@ static void redraw_mix_line (LIST *chain)
+@@ -190,7 +194,7 @@
if (t && t[0] == '0' && t[1] == '\0')
t = "";
@@ -354,7 +433,7 @@ index 9d87060..b63695f 100644
break;
addstr (NONULL(t));
-@@ -242,7 +242,7 @@ static void draw_envelope_addr (int line, ADDRESS *addr)
+@@ -242,20 +246,23 @@
buf[0] = 0;
rfc822_write_address (buf, sizeof (buf), addr, 1);
@@ -363,7 +442,12 @@ index 9d87060..b63695f 100644
mutt_paddstr (W, buf);
}
-@@ -252,10 +252,10 @@ static void draw_envelope (HEADER *msg, char *fcc)
+ static void draw_envelope (HEADER *msg, char *fcc)
+ {
++#ifdef USE_SIDEBAR
++ mutt_sb_draw();
++#endif
+ draw_envelope_addr (HDR_FROM, msg->env->from);
draw_envelope_addr (HDR_TO, msg->env->to);
draw_envelope_addr (HDR_CC, msg->env->cc);
draw_envelope_addr (HDR_BCC, msg->env->bcc);
@@ -376,7 +460,7 @@ index 9d87060..b63695f 100644
mutt_paddstr (W, fcc);
if (WithCrypto)
-@@ -266,7 +266,7 @@ static void draw_envelope (HEADER *msg, char *fcc)
+@@ -266,7 +273,7 @@
#endif
SETCOLOR (MT_COLOR_STATUS);
@@ -385,16 +469,25 @@ index 9d87060..b63695f 100644
clrtoeol ();
NORMAL_COLOR;
-@@ -302,7 +302,7 @@ static int edit_address_list (int line, ADDRESS **addr)
+@@ -302,7 +309,7 @@
/* redraw the expanded list so the user can see the result */
buf[0] = 0;
rfc822_write_address (buf, sizeof (buf), *addr, 1);
- move (line, HDR_XOFFSET);
-+ move (line, HDR_XOFFSET+SidebarWidth);
++ move (line, HDR_XOFFSET + SidebarWidth);
mutt_paddstr (W, buf);
return 0;
-@@ -562,7 +562,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */
+@@ -515,7 +522,7 @@
+ menu->tag = mutt_tag_attach;
+ menu->data = idx;
+ menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, ComposeHelp);
+-
++
+ while (loop)
+ {
+ switch (op = mutt_menuLoop (menu))
+@@ -564,7 +571,7 @@
if (mutt_get_field ("Subject: ", buf, sizeof (buf), 0) == 0)
{
mutt_str_replace (&msg->env->subject, buf);
@@ -403,7 +496,7 @@ index 9d87060..b63695f 100644
if (msg->env->subject)
mutt_paddstr (W, msg->env->subject);
else
-@@ -580,7 +580,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */
+@@ -582,7 +589,7 @@
{
strfcpy (fcc, buf, fcclen);
mutt_pretty_mailbox (fcc, fcclen);
@@ -412,57 +505,118 @@ index 9d87060..b63695f 100644
mutt_paddstr (W, fcc);
fccSet = 1;
}
-diff --git a/curs_main.c b/curs_main.c
-index 9d718ee..ea530a6 100644
---- a/curs_main.c
-+++ b/curs_main.c
-@@ -26,7 +26,9 @@
+diff -urN mutt-1.6.1/configure.ac mutt-1.6.1-sidebar/configure.ac
+--- mutt-1.6.1/configure.ac 2016-06-12 18:43:00.398447528 +0100
++++ mutt-1.6.1-sidebar/configure.ac 2016-06-12 18:43:03.952502951 +0100
+@@ -175,6 +175,14 @@
+ SMIMEAUX_TARGET="smime_keys"
+ fi
+
++AC_ARG_ENABLE(sidebar, AC_HELP_STRING([--enable-sidebar], [Enable Sidebar support]),
++[ if test x$enableval = xyes ; then
++ AC_DEFINE(USE_SIDEBAR, 1, [Define if you want support for the sidebar.])
++ OPS="$OPS \$(srcdir)/OPS.SIDEBAR"
++ MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS sidebar.o"
++ fi
++])
++
+ AC_ARG_WITH(mixmaster, AS_HELP_STRING([--with-mixmaster@<:@=PATH@:>@],[Include Mixmaster support]),
+ [if test "$withval" != no
+ then
+diff -urN mutt-1.6.1/copy.c mutt-1.6.1-sidebar/copy.c
+--- mutt-1.6.1/copy.c 2016-06-12 18:43:00.398447528 +0100
++++ mutt-1.6.1-sidebar/copy.c 2016-06-12 18:43:03.952502951 +0100
+@@ -288,7 +288,8 @@
+ if (flags & (CH_DECODE|CH_PREFIX))
+ {
+ if (mutt_write_one_header (out, 0, headers[x],
+- flags & CH_PREFIX ? prefix : 0, mutt_term_width (Wrap), flags) == -1)
++ flags & CH_PREFIX ? prefix : 0,
++ mutt_term_width (Wrap), flags) == -1)
+ {
+ error = TRUE;
+ break;
+diff -urN mutt-1.6.1/curs_main.c mutt-1.6.1-sidebar/curs_main.c
+--- mutt-1.6.1/curs_main.c 2016-06-12 18:43:00.399447544 +0100
++++ mutt-1.6.1-sidebar/curs_main.c 2016-06-12 18:43:03.953502966 +0100
+@@ -26,8 +26,13 @@
#include "mailbox.h"
#include "mapping.h"
#include "sort.h"
+#include "buffy.h"
#include "mx.h"
-+#include "sidebar.h"
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
++
#ifdef USE_POP
#include "pop.h"
-@@ -596,8 +598,12 @@ int mutt_index_menu (void)
+ #endif
+@@ -595,21 +600,39 @@
menu->redraw |= REDRAW_STATUS;
if (do_buffy_notify)
{
- if (mutt_buffy_notify () && option (OPTBEEPNEW))
- beep ();
-+ if (mutt_buffy_notify ())
++ if (mutt_buffy_notify())
+ {
-+ menu->redraw |= REDRAW_FULL;
++ menu->redraw |= REDRAW_STATUS;
+ if (option (OPTBEEPNEW))
-+ beep ();
++ beep();
+ }
}
else
do_buffy_notify = 1;
-@@ -609,6 +615,7 @@ int mutt_index_menu (void)
+ }
+
++#ifdef USE_SIDEBAR
++ if (option (OPTSIDEBAR))
++ menu->redraw |= REDRAW_SIDEBAR;
++#endif
++
+ if (op != -1)
+ mutt_curs_set (0);
+
if (menu->redraw & REDRAW_FULL)
{
menu_redraw_full (menu);
-+ draw_sidebar(menu->menu);
++#ifdef USE_SIDEBAR
++ mutt_sb_draw();
++#endif
mutt_show_error ();
}
++#ifdef USE_SIDEBAR
++ else if (menu->redraw & REDRAW_SIDEBAR) {
++ mutt_sb_draw();
++ menu->redraw &= ~REDRAW_SIDEBAR;
++ }
++#endif
-@@ -631,9 +638,12 @@ int mutt_index_menu (void)
+ if (menu->menu == MENU_MAIN)
+ {
+@@ -630,9 +653,20 @@
if (menu->redraw & REDRAW_STATUS)
{
-+ DrawFullLine = 1;
++#ifdef USE_SIDEBAR
++ /* Temporarily lie about the sidebar width */
++ short sw = SidebarWidth;
++ SidebarWidth = 0;
++#endif
menu_status_line (buf, sizeof (buf), menu, NONULL (Status));
-+ DrawFullLine = 0;
++#ifdef USE_SIDEBAR
++ SidebarWidth = sw; /* Restore the sidebar width */
++#endif
move (option (OPTSTATUSONTOP) ? 0 : LINES-2, 0);
SETCOLOR (MT_COLOR_STATUS);
-+ set_buffystats(Context);
++#ifdef USE_SIDEBAR
++ mutt_sb_set_buffystats (Context);
++#endif
mutt_paddstr (COLS, buf);
NORMAL_COLOR;
menu->redraw &= ~REDRAW_STATUS;
-@@ -653,7 +663,7 @@ int mutt_index_menu (void)
+@@ -652,7 +686,7 @@
menu->oldcurrent = -1;
if (option (OPTARROWCURSOR))
@@ -471,229 +625,1948 @@ index 9d718ee..ea530a6 100644
else if (option (OPTBRAILLEFRIENDLY))
move (menu->current - menu->top + menu->offset, 0);
else
-@@ -1154,6 +1164,7 @@ int mutt_index_menu (void)
+@@ -1091,6 +1125,9 @@
+ break;
+
+ CHECK_MSGCOUNT;
++#ifdef USE_SIDEBAR
++ CHECK_VISIBLE;
++#endif
+ CHECK_READONLY;
+ {
+ int oldvcount = Context->vcount;
+@@ -1150,6 +1187,9 @@
menu->redraw = REDRAW_FULL;
break;
++#ifdef USE_SIDEBAR
+ case OP_SIDEBAR_OPEN:
++#endif
case OP_MAIN_CHANGE_FOLDER:
case OP_MAIN_NEXT_UNREAD_MAILBOX:
-@@ -1185,7 +1196,11 @@ int mutt_index_menu (void)
+@@ -1181,6 +1221,14 @@
{
mutt_buffy (buf, sizeof (buf));
-- if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1)
-+ if ( op == OP_SIDEBAR_OPEN ) {
-+ if(!CurBuffy)
-+ break;
-+ strncpy( buf, CurBuffy->path, sizeof(buf) );
-+ } else if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1)
++#ifdef USE_SIDEBAR
++ if (op == OP_SIDEBAR_OPEN) {
++ const char *path = mutt_sb_get_highlight();
++ if (!path)
++ break;
++ strncpy (buf, path, sizeof (buf));
++ } else
++#endif
+ if (mutt_enter_fname (cp, buf, sizeof (buf), &menu->redraw, 1) == -1)
{
if (menu->menu == MENU_PAGER)
- {
-@@ -1203,6 +1218,7 @@ int mutt_index_menu (void)
+@@ -1199,6 +1247,9 @@
}
mutt_expand_path (buf, sizeof (buf));
-+ set_curbuffy(buf);
++#ifdef USE_SIDEBAR
++ mutt_sb_set_open_buffy (buf);
++#endif
if (mx_get_magic (buf) <= 0)
{
mutt_error (_("%s is not a mailbox."), buf);
-@@ -2306,6 +2322,12 @@ int mutt_index_menu (void)
+@@ -2310,6 +2361,21 @@
mutt_what_key();
break;
-+ case OP_SIDEBAR_SCROLL_UP:
-+ case OP_SIDEBAR_SCROLL_DOWN:
++#ifdef USE_SIDEBAR
+ case OP_SIDEBAR_NEXT:
++ case OP_SIDEBAR_NEXT_NEW:
++ case OP_SIDEBAR_PAGE_DOWN:
++ case OP_SIDEBAR_PAGE_UP:
+ case OP_SIDEBAR_PREV:
-+ scroll_sidebar(op, menu->menu);
++ case OP_SIDEBAR_PREV_NEW:
++ mutt_sb_change_mailbox (op);
+ break;
++
++ case OP_SIDEBAR_TOGGLE_VISIBLE:
++ toggle_option (OPTSIDEBAR);
++ menu->redraw = REDRAW_FULL;
++ break;
++#endif
default:
if (menu->menu == MENU_MAIN)
km_error_key (MENU_MAIN);
-diff --git a/flags.c b/flags.c
-index 133fa35..48fb287 100644
---- a/flags.c
-+++ b/flags.c
-@@ -22,8 +22,10 @@
+diff -urN mutt-1.6.1/doc/manual.xml.head mutt-1.6.1-sidebar/doc/manual.xml.head
+--- mutt-1.6.1/doc/manual.xml.head 2016-06-12 18:43:00.402447590 +0100
++++ mutt-1.6.1-sidebar/doc/manual.xml.head 2016-06-12 18:43:03.955502998 +0100
+@@ -405,6 +405,623 @@
+
+
+
++
++ Sidebar
++
++ The Sidebar shows a list of all your mailboxes. The list can be
++ turned on and off, it can be themed and the list style can be
++ configured.
++
++
++ This part of the manual is suitable for beginners.
++ If you already know Mutt you could skip ahead to the main
++ Sidebar guide.
++ If you just want to get started, you could use the sample
++ Sidebar muttrc.
++
++
++ This version of Sidebar is based on Terry Chan's
++ 2015-11-11 release.
++ It contains many
++ new features,
++ lots of
++ bugfixes
++ and a generous helping of
++ new documentation which you are already reading.
++
++
++ To check if Mutt supports Sidebar, look for the string
++ +USE_SIDEBAR in the mutt version.
++
++
++mutt -v
++
++
++ Let's turn on the Sidebar:
++
++ set sidebar_visible
++
++ You will see something like this.
++ A list of mailboxes on the left.
++ A list of emails, from the selected mailbox, on the right.
++
++
++Fruit [1] 3/8| 1 + Jan 24 Rhys Lee (192) Yew
++Animals [1] 2/6| 2 + Feb 11 Grace Hall (167) Ilama
++Cars 4| 3 Feb 23 Aimee Scott (450) Nectarine
++Seas 1/7| 4 ! Feb 28 Summer Jackson (264) Lemon
++ | 5 Mar 07 Callum Harrison (464) Raspberry
++ | 6 N + Mar 24 Samuel Harris (353) Tangerine
++ | 7 N + Sep 05 Sofia Graham (335) Cherry
++ | 8 N Sep 16 Ewan Brown (105) Ugli
++ |
++ |
++
++
++ This user has four mailboxes: Fruit,
++ Cars, Animals and
++ Seas.
++
++
++ The current, open, mailbox is Fruit. We can
++ also see information about the other mailboxes. For example:
++ The Animals mailbox contains, 1 flagged email, 2
++ new emails out of a total of 6 emails.
++
++
++ Navigation
++
++ The Sidebar adds some new functions
++ to Mutt.
++
++
++ The user pressed the c key to
++ <change-folder> to the
++ Animals mailbox. The Sidebar automatically
++ updated the indicator to match.
++
++
++Fruit [1] 3/8| 1 Jan 03 Tia Gibson (362) Caiman
++Animals [1] 2/6| 2 + Jan 22 Rhys Lee ( 48) Dolphin
++Cars 4| 3 ! Aug 16 Ewan Brown (333) Hummingbird
++Seas 1/7| 4 Sep 25 Grace Hall ( 27) Capybara
++ | 5 N + Nov 12 Evelyn Rogers (453) Tapir
++ | 6 N + Nov 16 Callum Harrison (498) Hedgehog
++ |
++ |
++ |
++ |
++
++
++ Let's map some functions:
++
++
++bind index,pager \CP sidebar-prev # Ctrl-Shift-P - Previous Mailbox
++bind index,pager \CN sidebar-next # Ctrl-Shift-N - Next Mailbox
++bind index,pager \CO sidebar-open # Ctrl-Shift-O - Open Highlighted Mailbox
++
++
++ Press Ctrl-Shift-N (Next mailbox) twice will
++ move the Sidebar highlight to
++ down to the Seas mailbox.
++
++
++Fruit [1] 3/8| 1 Jan 03 Tia Gibson (362) Caiman
++Animals [1] 2/6| 2 + Jan 22 Rhys Lee ( 48) Dolphin
++Cars 4| 3 ! Aug 16 Ewan Brown (333) Hummingbird
++Seas 1/7| 4 Sep 25 Grace Hall ( 27) Capybara
++ | 5 N + Nov 12 Evelyn Rogers (453) Tapir
++ | 6 N + Nov 16 Callum Harrison (498) Hedgehog
++ |
++ |
++ |
++ |
++
++
++ Functions <sidebar-next> and
++ <sidebar-prev> move the Sidebar
++ highlight.
++ They do not change the open
++ mailbox.
++
++
++ Press Ctrl-Shift-O
++ (<sidebar-open>)
++ to open the highlighted mailbox.
++
++
++Fruit [1] 3/8| 1 ! Mar 07 Finley Jones (139) Molucca Sea
++Animals [1] 2/6| 2 + Mar 24 Summer Jackson ( 25) Arafura Sea
++Cars 4| 3 + Feb 28 Imogen Baker (193) Pechora Sea
++Seas 1/7| 4 N + Feb 23 Isla Hussain (348) Balearic Sea
++ |
++ |
++ |
++ |
++ |
++ |
++
++
++
++ Features
++
++ The Sidebar shows a list of mailboxes in a panel.
++
++
++ Everything about the Sidebar can be configured.
++
++
++ State of the Sidebar
++ Visibility
++ Width
++
++
++ Which mailboxes are displayed
++ Display all
++ Limit to mailboxes with new mail
++ Whitelist mailboxes to display always
++
++
++ The order in which mailboxes are displayed
++
++ Unsorted (order of mailboxes commands)
++ Sorted alphabetically
++ Sorted by number of new mails
++
++
++ Color
++ Sidebar indicators and divider
++ Mailboxes depending on their type
++ Mailboxes depending on their contents
++
++
++ Key bindings
++ Hide/Unhide the Sidebar
++ Select previous/next mailbox
++ Select previous/next mailbox with new mail
++ Page up/down through a list of mailboxes
++
++
++ Misc
++ Formatting string for mailbox
++ Wraparound searching
++ Flexible mailbox abbreviations
++ Support for Unicode mailbox names (utf-8)
++
++
++
++ Display
++
++ Everything about the Sidebar can be configured.
++
++
++ For a quick reference:
++ Sidebar variables to set
++ Sidebar colors to apply
++ Sidebar sort methods
++
++
++ Sidebar Basics
++
++ The most important variable is $sidebar_visible.
++ You can set this in your muttrc, or bind a key to the
++ function <sidebar-toggle-visible>.
++
++
++set sidebar_visible # Make the Sidebar visible by default
++bind index,pager B sidebar-toggle-visible # Use 'B' to switch the Sidebar on and off
++
++
++ Next, decide how wide you want the Sidebar to be. 25
++ characters might be enough for the mailbox name and some numbers.
++ Remember, you can hide/show the Sidebar at the press of button.
++
++
++ Finally, you might want to change the divider character.
++ By default, Sidebar draws an ASCII line between it and the Index panel
++ If your terminal supports it, you can use a Unicode line-drawing character.
++
++
++set sidebar_width = 25 # Plenty of space
++set sidebar_divider_char = '│' # Pretty line-drawing character
++
++
++
++ Sidebar Format String
++
++ $sidebar_format allows you to customize the Sidebar display.
++ For an introduction, read format strings
++ including the section about conditionals.
++
++
++ The default value is %B%?F? [%F]?%* %?N?%N/?%S
++
++
++ Which breaks down as:
++ %B - Mailbox name
++ %?F? [%F]? - If flagged emails [%F], otherwise nothing
++ %* - Pad with spaces
++ %?N?%N/? - If new emails %N/, otherwise nothing
++ %S - Total number of emails
++
++
++ sidebar_format
++
++
++
++ Format
++ Notes
++ Description
++
++
++
++
++ %B
++
++ Name of the mailbox
++
++
++ %S
++ *
++ Size of mailbox (total number of messages)
++
++
++ %N
++ *
++ Number of New messages in the mailbox
++
++
++ %F
++ *
++ Number of Flagged messages in the mailbox
++
++
++ %!
++
++
++ !: one flagged message;
++ !!: two flagged messages;
++ n!: n flagged messages (for n > 2).
++ Otherwise prints nothing.
++
++
++
++ %d
++ * ‡
++ Number of deleted messages
++
++
++ %L
++ * ‡
++ Number of messages after limiting
++
++
++ %t
++ * ‡
++ Number of tagged messages
++
++
++ %>X
++
++ Right justify the rest of the string and pad with X
++
++
++ %|X
++
++ Pad to the end of the line with
++ X
++
++
++ %*X
++
++ Soft-fill with character Xas pad
++
++
++
++
++
++ * = Can be optionally printed if nonzero
++
++
++ ‡ = Only applicable to the current folder
++
++
++ Here are some examples.
++ They show the number of (F)lagged, (N)ew and (S)ize.
++
++
++
++
++ Abbreviating Mailbox Names
++
++ $sidebar_delim_chars tells Sidebar
++ how to split up mailbox paths. For local directories
++ use /; for IMAP folders use .
++
++
++ Example 1
++
++ This example works well if your mailboxes have unique names
++ after the last separator.
++
++
++ Add some mailboxes of diffent depths.
++
++
++set folder="~/mail"
++mailboxes =fruit/apple =fruit/banana =fruit/cherry
++mailboxes =water/sea/sicily =water/sea/archipelago =water/sea/sibuyan
++mailboxes =water/ocean/atlantic =water/ocean/pacific =water/ocean/arctic
++
++
++ Shorten the names:
++
++
++set sidebar_short_path # Shorten mailbox names
++set sidebar_delim_chars="/" # Delete everything up to the last / character
++
++
++ The screenshot below shows what the Sidebar would look like
++ before and after shortening.
++
++
++|fruit/apple |apple
++|fruit/banana |banana
++|fruit/cherry |cherry
++|water/sea/sicily |sicily
++|water/sea/archipelago |archipelago
++|water/sea/sibuyan |sibuyan
++|water/ocean/atlantic |atlantic
++|water/ocean/pacific |pacific
++|water/ocean/arctic |arctic
++
++
++
++ Example 2
++
++ This example works well if you have lots of mailboxes which are arranged
++ in a tree.
++
++
++ Add some mailboxes of diffent depths.
++
++
++set folder="~/mail"
++mailboxes =fruit
++mailboxes =fruit/apple =fruit/banana =fruit/cherry
++mailboxes =water
++mailboxes =water/sea
++mailboxes =water/sea/sicily =water/sea/archipelago =water/sea/sibuyan
++mailboxes =water/ocean
++mailboxes =water/ocean/atlantic =water/ocean/pacific =water/ocean/arctic
++
++
++ Shorten the names:
++
++
++set sidebar_short_path # Shorten mailbox names
++set sidebar_delim_chars="/" # Delete everything up to the last / character
++set sidebar_folder_indent # Indent folders whose names we've shortened
++set sidebar_indent_string=" " # Indent with two spaces
++
++
++ The screenshot below shows what the Sidebar would look like
++ before and after shortening.
++
++
++|fruit |fruit
++|fruit/apple | apple
++|fruit/banana | banana
++|fruit/cherry | cherry
++|water |water
++|water/sea | sea
++|water/sea/sicily | sicily
++|water/sea/archipelago | archipelago
++|water/sea/sibuyan | sibuyan
++|water/ocean | ocean
++|water/ocean/atlantic | atlantic
++|water/ocean/pacific | pacific
++|water/ocean/arctic | arctic
++
++
++ Sometimes, it will be necessary to add mailboxes, that you
++ don't use, to fill in part of the tree. This will trade
++ vertical space for horizonal space (but it looks good).
++
++
++
++
++ Limiting the Number of Mailboxes
++
++ If you have a lot of mailboxes, sometimes it can be useful to hide
++ the ones you aren't using. $sidebar_new_mail_only
++ tells Sidebar to only show mailboxes that contain new, or flagged, email.
++
++
++ If you want some mailboxes to be always visible, then use the
++ sidebar_whitelist command. It takes a list of
++ mailboxes as parameters.
++
++
++set sidebar_new_mail_only # Only mailboxes with new/flagged email
++sidebar_whitelist fruit fruit/apple # Always display these two mailboxes
++
++
++
++
++ Colors
++
++ Here is a sample color scheme:
++
++
++color sidebar_indicator default color17 # Dark blue background
++color sidebar_highlight white color238 # Grey background
++color sidebar_spoolfile yellow default # Yellow
++color sidebar_new green default # Green
++color sidebar_flagged red default # Red
++color sidebar_divider color8 default # Dark grey
++
++
++ There is a priority order when coloring Sidebar mailboxes.
++ e.g. If a mailbox has new mail it will have the
++ sidebar_new color, even if it also contains
++ flagged mails.
++
++
++ Sidebar Color Priority
++
++
++
++ Priority
++ Color
++ Description
++
++
++
++
++ Highest
++ sidebar_indicator
++ Mailbox is open
++
++
++
++ sidebar_highlight
++ Mailbox is highlighed
++
++
++
++ sidebar_spoolfile
++ Mailbox is the spoolfile (receives incoming mail)
++
++
++
++ sidebar_new
++ Mailbox contains new mail
++
++
++
++ sidebar_flagged
++ Mailbox contains flagged mail
++
++
++ Lowest
++ (None)
++ Mailbox does not match above
++
++
++
++
++
++
++ Bug-fixes
++
++ If you haven't used Sidebar before, you can ignore this section.
++
++
++ These bugs have been fixed since the previous Sidebar release: 2015-11-11.
++
++
++ Fix bug when starting in compose mode
++ Fix bug with empty sidebar_divider_char string
++ Fix bug with header wrapping
++ Correctly handle utf8 character sequences
++ Fix a bug in mh_buffy_update
++ Fix refresh -- time overflowed short
++ Protect against empty format strings
++ Limit Sidebar width to COLS
++ Handle unmailboxes * safely
++ Refresh Sidebar after timeout
++
++
++
++ Config Changes
++
++ If you haven't used Sidebar before, you can ignore this section.
++
++
++ Some of the Sidebar config has been changed to make its meaning clearer.
++ These changes have been made since the previous Sidebar release: 2015-11-11.
++
++
++
++
++
+
+ Help
+
+@@ -6773,6 +7390,17 @@
+
+
+
++Mutt will set the COLUMNS environment variable to
++the width of the pager. Some programs make use of this environment
++variable automatically. Others provide a command line argument that
++can use this to set the output width:
++
++
++
++text/html; lynx -dump -width ${COLUMNS:-80} %s; copiousoutput
++
++
++
+ Note that when using the built-in pager, only
+ entries with this flag will be considered a handler for a MIME type
+ — all other entries will be ignored.
+@@ -7467,6 +8095,16 @@
+
+
+
++
++Mutt Patches
++
++Mutt may also be patched to support smaller features.
++These patches should add a free-form string to the end Mutt's version string.
++Running mutt -v might show:
++patch-1.6.1.sidebar.20160502
++
++
++
+
+ URL Syntax
+
+@@ -8081,6 +8719,469 @@
+
+
+
++
++ Sidebar Patch
++ Overview of mailboxes
++
++
++ Patch
++
++
++ To check if Mutt supports Sidebar, look for
++ +USE_SIDEBAR in the mutt version.
++ See: .
++
++
++
++ Dependencies:
++ mutt-1.6.1
++
++
++ This patch is part of the NeoMutt Project.
++
++
++
++ Introduction
++
++
++ The Sidebar shows a list of all your mailboxes. The list can be
++ turned on and off, it can be themed and the list style can be
++ configured.
++
++
++
++ This part of the manual is a reference guide.
++ If you want a simple introduction with examples see the
++ Sidebar Howto.
++ If you just want to get started, you could use the sample
++ Sidebar muttrc.
++
++
++
++ This version of Sidebar is based on Terry Chan's
++ 2015-11-11 release.
++ It contains many
++ new features,
++ lots of
++ bugfixes.
++
++
++
++
++ Variables
++
++
++ Sidebar Colors
++
++
++
++ Name
++ Default Color
++ Description
++
++
++
++
++ sidebar_divider
++ default
++ The dividing line between the Sidebar and the Index/Pager panels
++
++
++ sidebar_flagged
++ default
++ Mailboxes containing flagged mail
++
++
++ sidebar_highlight
++ underline
++ Cursor to select a mailbox
++
++
++ sidebar_indicator
++ mutt indicator
++ The mailbox open in the Index panel
++
++
++ sidebar_new
++ default
++ Mailboxes containing new mail
++
++
++ sidebar_spoolfile
++ default
++ Mailbox that receives incoming mail
++
++
++
++
++
++ If the sidebar_indicator color isn't set, then the default Mutt
++ indicator color will be used (the color used in the index panel).
++
++
++
++ Sort
++
++
++ Sidebar Sort
++
++
++
++ Sort
++ Description
++
++
++
++
++ alpha
++ Alphabetically by path
++
++
++ count
++ Total number of messages
++
++
++ flagged
++ Number of flagged messages
++
++
++ name
++ Alphabetically by path
++
++
++ new
++ Number of new messages
++
++
++ path
++ Alphabetically by path
++
++
++ unsorted
++ Do not resort the paths
++
++
++
++
++
++
++
++ Muttrc
++
++# This is a complete list of sidebar-related configuration.
++
++# --------------------------------------------------------------------------
++# VARIABLES - shown with their default values
++# --------------------------------------------------------------------------
++
++# Should the Sidebar be shown?
++set sidebar_visible = no
++
++# How wide should the Sidebar be in screen columns?
++# Note: Some characters, e.g. Chinese, take up two columns each.
++set sidebar_width = 20
++
++# Should the mailbox paths be abbreviated?
++set sidebar_short_path = no
++
++# When abbreviating mailbox path names, use any of these characters as path
++# separators. Only the part after the last separators will be shown.
++# For file folders '/' is good. For IMAP folders, often '.' is useful.
++set sidebar_delim_chars = '/.'
++
++# If the mailbox path is abbreviated, should it be indented?
++set sidebar_folder_indent = no
++
++# Indent mailbox paths with this string.
++set sidebar_indent_string = ' '
++
++# Make the Sidebar only display mailboxes that contain new, or flagged,
++# mail.
++set sidebar_new_mail_only = no
++
++# Any mailboxes that are whitelisted will always be visible, even if the
++# sidebar_new_mail_only option is enabled.
++sidebar_whitelist '/home/user/mailbox1'
++sidebar_whitelist '/home/user/mailbox2'
++
++# When searching for mailboxes containing new mail, should the search wrap
++# around when it reaches the end of the list?
++set sidebar_next_new_wrap = no
++
++# The character to use as the divider between the Sidebar and the other Mutt
++# panels.
++# Note: Only the first character of this string is used.
++set sidebar_divider_char = '|'
++
++# Display the Sidebar mailboxes using this format string.
++set sidebar_format = '%B%?F? [%F]?%* %?N?%N/?%S'
++
++# Sidebar will not refresh its list of mailboxes any more frequently than
++# this number of seconds. This will help reduce disk/network traffic.
++set sidebar_refresh_time = 60
++
++# Sort the mailboxes in the Sidebar using this method:
++# count - total number of messages
++# flagged - number of flagged messages
++# new - number of new messages
++# path - mailbox path
++# unsorted - do not sort the mailboxes
++set sidebar_sort_method = 'unsorted'
++
++# --------------------------------------------------------------------------
++# FUNCTIONS - shown with an example mapping
++# --------------------------------------------------------------------------
++
++# Move the highlight to the previous mailbox
++bind index,pager \Cp sidebar-prev
++
++# Move the highlight to the next mailbox
++bind index,pager \Cn sidebar-next
++
++# Open the highlighted mailbox
++bind index,pager \Co sidebar-open
++
++# Move the highlight to the previous page
++# This is useful if you have a LOT of mailboxes.
++bind index,pager <F3> sidebar-page-up
++
++# Move the highlight to the next page
++# This is useful if you have a LOT of mailboxes.
++bind index,pager <F4> sidebar-page-down
++
++# Move the highlight to the previous mailbox containing new, or flagged,
++# mail.
++bind index,pager <F5> sidebar-prev-new
++
++# Move the highlight to the next mailbox containing new, or flagged, mail.
++bind index,pager <F6> sidebar-next-new
++
++# Toggle the visibility of the Sidebar.
++bind index,pager B sidebar-toggle-visible
++
++# --------------------------------------------------------------------------
++# COLORS - some unpleasant examples are given
++# --------------------------------------------------------------------------
++# Note: All color operations are of the form:
++# color OBJECT FOREGROUND BACKGROUND
++
++# Color of the current, open, mailbox
++# Note: This is a general Mutt option which colors all selected items.
++color indicator cyan black
++
++# Color of the highlighted, but not open, mailbox.
++color sidebar_highlight black color8
++
++# Color of the divider separating the Sidebar from Mutt panels
++color sidebar_divider color8 black
++
++# Color to give mailboxes containing flagged mail
++color sidebar_flagged red black
++
++# Color to give mailboxes containing new mail
++color sidebar_new green black
++
++# --------------------------------------------------------------------------
++
++# vim: syntax=muttrc
++
++
++
++
++ See Also
++
++
++ Regular Expressions
++ Patterns
++ Color command
++ notmuch patch
++
++
++
++
++ Known Bugs
++ Unsorted isn't
++
++
++
++ Credits
++
++ Justin Hibbits jrh29@po.cwru.edu
++ Thomer M. Gil mutt@thomer.com
++ David Sterba dsterba@suse.cz
++ Evgeni Golov evgeni@debian.org
++ Fabian Groffen grobian@gentoo.org
++ Jason DeTiberus jdetiber@redhat.com
++ Stefan Assmann sassmann@kpanic.de
++ Steve Kemp steve@steve.org.uk
++ Terry Chan tchan@lunar-linux.org
++ Tyler Earnest tylere@rne.st
++ Richard Russon rich@flatcap.org
++
++
++
++
+
+
+
+@@ -9237,6 +10338,17 @@
+
+
+
++sidebar_whitelist
++
++item
++
++
++command
++
++
++
++
++
+ source
+
+ filename
+diff -urN mutt-1.6.1/doc/mutt.css mutt-1.6.1-sidebar/doc/mutt.css
+--- mutt-1.6.1/doc/mutt.css 2016-06-12 18:43:00.402447590 +0100
++++ mutt-1.6.1-sidebar/doc/mutt.css 2016-06-12 18:43:03.811500752 +0100
+@@ -9,17 +9,24 @@
+ div.table-contents table th, div.informaltable table th {
+ font-family:sans-serif;
+ background:#d0d0d0;
+- font-weight:normal;
++ font-weight:bold;
+ vertical-align:top;
+ }
+-div.cmdsynopsis { border-left:1px solid #707070; padding-left:5px; }
++div.cmdsynopsis { border-left:1px solid #707070; padding-left: 1em; }
+ li div.cmdsynopsis { border-left:none; padding-left:0px; }
+-pre.screen, div.note { background:#f0f0f0; border:1px solid #c0c0c0; padding:5px; margin-left:2%; margin-right:2%; }
++li p { margin: 0; }
++pre.screen, div.note { border:1px solid #c0c0c0; margin-left:2%; margin-right:2%; }
++pre.screen { color: #ffffff; background:#000000; padding: 0.5em; }
++div.note { background:#ffff80; padding: 0.5em; }
+ div.example p.title { margin-left:2%; }
+ div.note h3 { font-size:small; font-style:italic; font-variant: small-caps; }
+ div.note h3:after { content: ":" }
+ div.note { margin-bottom: 5px; }
+-.command { font-family: monospace; font-weight: normal; }
++div.literallayout, .command { font-family: monospace; font-weight: normal; }
+ .command strong { font-weight: normal; }
+ tr { vertical-align: top; }
+-.comment { color:#707070; }
++.comment { color:#00c000; }
++code.literal { background: #f0f0f0; color: #000000; }
++span.indicator { background: #000060; color: #ffffff; }
++span.highlight { background: #404040; color: #ffffff; }
++span.reverse { background: #ffffff; color: #000000; }
+diff -urN mutt-1.6.1/doc/muttrc.sidebar mutt-1.6.1-sidebar/doc/muttrc.sidebar
+--- mutt-1.6.1/doc/muttrc.sidebar 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/doc/muttrc.sidebar 2016-06-12 18:43:03.812500768 +0100
+@@ -0,0 +1,116 @@
++# This is a complete list of sidebar-related configuration.
++
++# --------------------------------------------------------------------------
++# VARIABLES - shown with their default values
++# --------------------------------------------------------------------------
++
++# Should the Sidebar be shown?
++set sidebar_visible = no
++
++# How wide should the Sidebar be in screen columns?
++# Note: Some characters, e.g. Chinese, take up two columns each.
++set sidebar_width = 20
++
++# Should the mailbox paths be abbreviated?
++set sidebar_short_path = no
++
++# When abbreviating mailbox path names, use any of these characters as path
++# separators. Only the part after the last separators will be shown.
++# For file folders '/' is good. For IMAP folders, often '.' is useful.
++set sidebar_delim_chars = '/.'
++
++# If the mailbox path is abbreviated, should it be indented?
++set sidebar_folder_indent = no
++
++# Indent mailbox paths with this string.
++set sidebar_indent_string = ' '
++
++# Make the Sidebar only display mailboxes that contain new, or flagged,
++# mail.
++set sidebar_new_mail_only = no
++
++# Any mailboxes that are whitelisted will always be visible, even if the
++# sidebar_new_mail_only option is enabled.
++sidebar_whitelist '/home/user/mailbox1'
++sidebar_whitelist '/home/user/mailbox2'
++
++# When searching for mailboxes containing new mail, should the search wrap
++# around when it reaches the end of the list?
++set sidebar_next_new_wrap = no
++
++# The character to use as the divider between the Sidebar and the other Mutt
++# panels.
++# Note: Only the first character of this string is used.
++set sidebar_divider_char = '|'
++
++# Display the Sidebar mailboxes using this format string.
++set sidebar_format = '%B%?F? [%F]?%* %?N?%N/?%S'
++
++# Sidebar will not refresh its list of mailboxes any more frequently than
++# this number of seconds. This will help reduce disk/network traffic.
++set sidebar_refresh_time = 60
++
++# Sort the mailboxes in the Sidebar using this method:
++# count - total number of messages
++# flagged - number of flagged messages
++# new - number of new messages
++# path - mailbox path
++# unsorted - do not sort the mailboxes
++set sidebar_sort_method = 'unsorted'
++
++# --------------------------------------------------------------------------
++# FUNCTIONS - shown with an example mapping
++# --------------------------------------------------------------------------
++
++# Move the highlight to the previous mailbox
++bind index,pager \Cp sidebar-prev
++
++# Move the highlight to the next mailbox
++bind index,pager \Cn sidebar-next
++
++# Open the highlighted mailbox
++bind index,pager \Co sidebar-open
++
++# Move the highlight to the previous page
++# This is useful if you have a LOT of mailboxes.
++bind index,pager sidebar-page-up
++
++# Move the highlight to the next page
++# This is useful if you have a LOT of mailboxes.
++bind index,pager sidebar-page-down
++
++# Move the highlight to the previous mailbox containing new, or flagged,
++# mail.
++bind index,pager sidebar-prev-new
++
++# Move the highlight to the next mailbox containing new, or flagged, mail.
++bind index,pager sidebar-next-new
++
++# Toggle the visibility of the Sidebar.
++bind index,pager B sidebar-toggle-visible
++
++# --------------------------------------------------------------------------
++# COLORS - some unpleasant examples are given
++# --------------------------------------------------------------------------
++# Note: All color operations are of the form:
++# color OBJECT FOREGROUND BACKGROUND
++
++# Color of the current, open, mailbox
++# Note: This is a general Mutt option which colors all selected items.
++color indicator cyan black
++
++# Color of the highlighted, but not open, mailbox.
++color sidebar_highlight black color8
++
++# Color of the divider separating the Sidebar from Mutt panels
++color sidebar_divider color8 black
++
++# Color to give mailboxes containing flagged mail
++color sidebar_flagged red black
++
++# Color to give mailboxes containing new mail
++color sidebar_new green black
++
++# --------------------------------------------------------------------------
++
++# vim: syntax=muttrc
+diff -urN mutt-1.6.1/doc/vimrc.sidebar mutt-1.6.1-sidebar/doc/vimrc.sidebar
+--- mutt-1.6.1/doc/vimrc.sidebar 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/doc/vimrc.sidebar 2016-06-12 18:43:03.813500783 +0100
+@@ -0,0 +1,35 @@
++" Vim syntax file for the mutt sidebar patch
++
++syntax keyword muttrcVarBool skipwhite contained sidebar_folder_indent nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarBool skipwhite contained sidebar_new_mail_only nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarBool skipwhite contained sidebar_next_new_wrap nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarBool skipwhite contained sidebar_short_path nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarBool skipwhite contained sidebar_visible nextgroup=muttrcSetBoolAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++
++syntax keyword muttrcVarNum skipwhite contained sidebar_refresh_time nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++syntax keyword muttrcVarNum skipwhite contained sidebar_width nextgroup=muttrcSetNumAssignment,muttrcVPrefix,muttrcVarBool,muttrcVarQuad,muttrcVarNum,muttrcVarStr
++
++syntax keyword muttrcVarStr contained skipwhite sidebar_divider_char nextgroup=muttrcVarEqualsIdxFmt
++syntax keyword muttrcVarStr contained skipwhite sidebar_delim_chars nextgroup=muttrcVarEqualsIdxFmt
++syntax keyword muttrcVarStr contained skipwhite sidebar_format nextgroup=muttrcVarEqualsIdxFmt
++syntax keyword muttrcVarStr contained skipwhite sidebar_indent_string nextgroup=muttrcVarEqualsIdxFmt
++syntax keyword muttrcVarStr contained skipwhite sidebar_sort_method nextgroup=muttrcVarEqualsIdxFmt
++
++syntax keyword muttrcCommand sidebar_whitelist
++
++syntax match muttrcFunction contained "\"
++syntax match muttrcFunction contained "\"
++syntax match muttrcFunction contained "\"
++syntax match muttrcFunction contained "\"
++syntax match muttrcFunction contained "\"
++syntax match muttrcFunction contained "\"
++syntax match muttrcFunction contained "\"
++syntax match muttrcFunction contained "\"
++
++syntax keyword muttrcColorField contained sidebar_divider
++syntax keyword muttrcColorField contained sidebar_flagged
++syntax keyword muttrcColorField contained sidebar_highlight
++syntax keyword muttrcColorField contained sidebar_indicator
++syntax keyword muttrcColorField contained sidebar_new
++
++" vim: syntax=vim
+diff -urN mutt-1.6.1/filter.c mutt-1.6.1-sidebar/filter.c
+--- mutt-1.6.1/filter.c 2016-06-12 18:43:00.403447606 +0100
++++ mutt-1.6.1-sidebar/filter.c 2016-06-12 18:43:03.835501127 +0100
+@@ -21,6 +21,7 @@
+ #endif
#include "mutt.h"
- #include "mutt_curses.h"
-+#include "mutt_menu.h"
++#include "mutt_curses.h"
+
+ #include
+ #include
+@@ -34,6 +35,7 @@
+ int fdin, int fdout, int fderr)
+ {
+ int pin[2], pout[2], perr[2], thepid;
++ char columns[11];
+
+ if (in)
+ {
+@@ -117,6 +119,9 @@
+ close (fderr);
+ }
+
++ snprintf (columns, sizeof (columns), "%d", COLS - SidebarWidth);
++ setenv ("COLUMNS", columns, 1);
++
+ execl (EXECSHELL, "sh", "-c", cmd, NULL);
+ _exit (127);
+ }
+diff -urN mutt-1.6.1/flags.c mutt-1.6.1-sidebar/flags.c
+--- mutt-1.6.1/flags.c 2016-06-12 18:43:00.403447606 +0100
++++ mutt-1.6.1-sidebar/flags.c 2016-06-12 18:43:03.956503013 +0100
+@@ -25,6 +25,10 @@
#include "sort.h"
#include "mx.h"
-+#include "sidebar.h"
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
++
void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
{
-@@ -290,6 +292,7 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
+ int changed = h->changed;
+@@ -263,6 +267,9 @@
*/
if (h->searched && (changed != h->changed || deleted != ctx->deleted || tagged != ctx->tagged || flagged != ctx->flagged))
h->searched = 0;
-+ draw_sidebar(0);
++#ifdef USE_SIDEBAR
++ mutt_sb_draw();
++#endif
}
void mutt_tag_set_flag (int flag, int bf)
-diff --git a/functions.h b/functions.h
-index 26171a0..ef8937a 100644
---- a/functions.h
-+++ b/functions.h
-@@ -170,6 +170,11 @@ const struct binding_t OpMain[] = { /* map: index */
+diff -urN mutt-1.6.1/functions.h mutt-1.6.1-sidebar/functions.h
+--- mutt-1.6.1/functions.h 2016-06-12 18:43:00.403447606 +0100
++++ mutt-1.6.1-sidebar/functions.h 2016-06-12 18:43:03.956503013 +0100
+@@ -168,6 +168,16 @@
+ { "decrypt-copy", OP_DECRYPT_COPY, NULL },
{ "decrypt-save", OP_DECRYPT_SAVE, NULL },
++#ifdef USE_SIDEBAR
++ { "sidebar-next", OP_SIDEBAR_NEXT, NULL },
++ { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL },
++ { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
++ { "sidebar-page-down", OP_SIDEBAR_PAGE_DOWN, NULL },
++ { "sidebar-page-up", OP_SIDEBAR_PAGE_UP, NULL },
++ { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
++ { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL },
++ { "sidebar-toggle-visible", OP_SIDEBAR_TOGGLE_VISIBLE, NULL },
++#endif
-+ { "sidebar-scroll-up", OP_SIDEBAR_SCROLL_UP, NULL },
-+ { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL },
-+ { "sidebar-next", OP_SIDEBAR_NEXT, NULL },
-+ { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
-+ { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
{ NULL, 0, NULL }
};
-
-@@ -274,6 +279,11 @@ const struct binding_t OpPager[] = { /* map: pager */
+@@ -272,6 +282,17 @@
{ "what-key", OP_WHAT_KEY, NULL },
-+ { "sidebar-scroll-up", OP_SIDEBAR_SCROLL_UP, NULL },
-+ { "sidebar-scroll-down", OP_SIDEBAR_SCROLL_DOWN, NULL },
-+ { "sidebar-next", OP_SIDEBAR_NEXT, NULL },
-+ { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
-+ { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
++#ifdef USE_SIDEBAR
++ { "sidebar-next", OP_SIDEBAR_NEXT, NULL },
++ { "sidebar-next-new", OP_SIDEBAR_NEXT_NEW, NULL },
++ { "sidebar-open", OP_SIDEBAR_OPEN, NULL },
++ { "sidebar-page-down", OP_SIDEBAR_PAGE_DOWN, NULL },
++ { "sidebar-page-up", OP_SIDEBAR_PAGE_UP, NULL },
++ { "sidebar-prev", OP_SIDEBAR_PREV, NULL },
++ { "sidebar-prev-new", OP_SIDEBAR_PREV_NEW, NULL },
++ { "sidebar-toggle-visible", OP_SIDEBAR_TOGGLE_VISIBLE, NULL },
++#endif
++
{ NULL, 0, NULL }
};
-diff --git a/globals.h b/globals.h
-index 282fde3..004c795 100644
---- a/globals.h
-+++ b/globals.h
-@@ -118,6 +118,7 @@ WHERE short SearchContext;
+diff -urN mutt-1.6.1/globals.h mutt-1.6.1-sidebar/globals.h
+--- mutt-1.6.1/globals.h 2016-06-12 18:43:00.403447606 +0100
++++ mutt-1.6.1-sidebar/globals.h 2016-06-12 18:43:03.956503013 +0100
+@@ -118,6 +118,12 @@
WHERE char *SendCharset;
WHERE char *Sendmail;
WHERE char *Shell;
-+WHERE char *SidebarDelim;
++#ifdef USE_SIDEBAR
++WHERE char *SidebarDelimChars;
++WHERE char *SidebarDividerChar;
++WHERE char *SidebarFormat;
++WHERE char *SidebarIndentString;
++#endif
WHERE char *Signature;
WHERE char *SimpleSearch;
#if USE_SMTP
-@@ -214,6 +215,9 @@ WHERE short ScoreThresholdDelete;
+@@ -214,6 +220,14 @@
WHERE short ScoreThresholdRead;
WHERE short ScoreThresholdFlag;
-+WHERE struct buffy_t *CurBuffy INITVAL(0);
-+WHERE short DrawFullLine INITVAL(0);
++/* This isn't excluded from the build because it's too entwined in the code.
++ * For now. */
+WHERE short SidebarWidth;
++#ifdef USE_SIDEBAR
++WHERE short SidebarRefreshTime;
++WHERE LIST *SidebarWhitelist INITVAL(0);
++#endif
++
#ifdef USE_IMAP
WHERE short ImapKeepalive;
WHERE short ImapPipelineDepth;
-diff --git a/imap/command.c b/imap/command.c
-index 32f8417..d68e3ab 100644
---- a/imap/command.c
-+++ b/imap/command.c
-@@ -1012,6 +1012,13 @@ static void cmd_parse_status (IMAP_DATA* idata, char* s)
+diff -urN mutt-1.6.1/imap/command.c mutt-1.6.1-sidebar/imap/command.c
+--- mutt-1.6.1/imap/command.c 2016-06-12 18:43:00.405447637 +0100
++++ mutt-1.6.1-sidebar/imap/command.c 2016-06-12 18:43:03.839501189 +0100
+@@ -1016,6 +1016,14 @@
opened */
status->uidnext = oldun;
-+ /* Added to make the sidebar show the correct numbers */
-+ if (status->messages)
-+ {
-+ inc->msgcount = status->messages;
-+ inc->msg_unread = status->unseen;
-+ }
++#ifdef USE_SIDEBAR
++ /* Make the sidebar show the correct numbers */
++ if (status->messages) {
++ inc->msg_count = status->messages;
++ inc->msg_unread = status->unseen;
++ }
++#endif
+
FREE (&value);
return;
}
-diff --git a/imap/imap.c b/imap/imap.c
-index f476873..af3ac3d 100644
---- a/imap/imap.c
-+++ b/imap/imap.c
-@@ -1529,7 +1529,7 @@ int imap_buffy_check (int force)
+diff -urN mutt-1.6.1/imap/imap.c mutt-1.6.1-sidebar/imap/imap.c
+--- mutt-1.6.1/imap/imap.c 2016-06-12 18:43:00.405447637 +0100
++++ mutt-1.6.1-sidebar/imap/imap.c 2016-06-12 18:43:03.958503044 +0100
+@@ -1535,7 +1535,11 @@
- imap_munge_mbox_name (munged, sizeof (munged), name);
+ imap_munge_mbox_name (idata, munged, sizeof (munged), name);
snprintf (command, sizeof (command),
-- "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT)", munged);
++#ifdef USE_SIDEBAR
+ "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT MESSAGES)", munged);
++#else
+ "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT)", munged);
++#endif
if (imap_exec (idata, command, IMAP_CMD_QUEUE) < 0)
{
-diff --git a/init.h b/init.h
-index 35224c1..c664e5f 100644
---- a/init.h
-+++ b/init.h
-@@ -2030,6 +2030,27 @@ struct option_t MuttVars[] = {
- ** not used.
- ** (PGP only)
+diff -urN mutt-1.6.1/init.c mutt-1.6.1-sidebar/init.c
+--- mutt-1.6.1/init.c 2016-06-12 18:43:00.406447652 +0100
++++ mutt-1.6.1-sidebar/init.c 2016-06-12 18:43:03.959503060 +0100
+@@ -2173,6 +2173,9 @@
+ case DT_SORT_AUX:
+ map = SortAuxMethods;
+ break;
++ case DT_SORT_SIDEBAR:
++ map = SortSidebarMethods;
++ break;
+ default:
+ map = SortMethods;
+ break;
+diff -urN mutt-1.6.1/init.h mutt-1.6.1-sidebar/init.h
+--- mutt-1.6.1/init.h 2016-06-12 18:43:00.408447684 +0100
++++ mutt-1.6.1-sidebar/init.h 2016-06-12 18:43:03.960503075 +0100
+@@ -42,11 +42,12 @@
+ #define DTYPE(x) ((x) & DT_MASK)
+
+ /* subtypes */
+-#define DT_SUBTYPE_MASK 0xf0
++#define DT_SUBTYPE_MASK 0xff0
+ #define DT_SORT_ALIAS 0x10
+ #define DT_SORT_BROWSER 0x20
+ #define DT_SORT_KEYS 0x40
+ #define DT_SORT_AUX 0x80
++#define DT_SORT_SIDEBAR 0x100
+
+ /* flags to parse_set() */
+ #define M_SET_INV (1<<0) /* default is to invert all vars */
+@@ -2665,6 +2666,147 @@
+ ** Command to use when spawning a subshell. By default, the user's login
+ ** shell from \fC/etc/passwd\fP is used.
*/
-+ {"sidebar_delim", DT_STR, R_BOTH, UL &SidebarDelim, "|"},
++#ifdef USE_SIDEBAR
++ { "sidebar_divider_char", DT_STR, R_BOTH, UL &SidebarDividerChar, UL "|" },
+ /*
+ ** .pp
-+ ** This specifies the delimiter between the sidebar (if visible) and
-+ ** other screens.
++ ** This specifies the characters to be drawn between the sidebar (when
++ ** visible) and the other Mutt panels. ASCII and Unicode line-drawing
++ ** characters are supported.
++ */
++ { "sidebar_delim_chars", DT_STR, R_NONE, UL &SidebarDelimChars, UL "/." },
++ /*
++ ** .pp
++ ** This contains the list of characters which you would like to treat
++ ** as folder separators for displaying paths in the sidebar.
++ ** .pp
++ ** Local mail is often arranged in directories: `dir1/dir2/mailbox'.
++ ** .ts
++ ** set sidebar_delim_chars='/'
++ ** .te
++ ** .pp
++ ** IMAP mailboxes are often named: `folder1.folder2.mailbox'.
++ ** .ts
++ ** set sidebar_delim_chars='.'
++ ** .te
++ ** .pp
++ ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_folder_indent, $$sidebar_indent_string.
++ */
++ { "sidebar_folder_indent", DT_BOOL, R_BOTH, OPTSIDEBARFOLDERINDENT, 0 },
++ /*
++ ** .pp
++ ** Set this to indent mailboxes in the sidebar.
++ ** .pp
++ ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_indent_string, $$sidebar_delim_chars.
++ */
++ { "sidebar_format", DT_STR, R_NONE, UL &SidebarFormat, UL "%B%?F? [%F]?%* %?N?%N/?%S" },
++ /*
++ ** .pp
++ ** This variable allows you to customize the sidebar display. This string is
++ ** similar to $$index_format, but has its own set of \fCprintf(3)\fP-like
++ ** sequences:
++ ** .dl
++ ** .dt %B .dd Name of the mailbox
++ ** .dt %S .dd * Size of mailbox (total number of messages)
++ ** .dt %N .dd * Number of New messages in the mailbox
++ ** .dt %F .dd * Number of Flagged messages in the mailbox
++ ** .dt %! .dd ``!'' : one flagged message;
++ ** ``!!'' : two flagged messages;
++ ** ``n!'' : n flagged messages (for n > 2).
++ ** Otherwise prints nothing.
++ ** .dt %d .dd * @ Number of deleted messages
++ ** .dt %L .dd * @ Number of messages after limiting
++ ** .dt %t .dd * @ Number of tagged messages
++ ** .dt %>X .dd right justify the rest of the string and pad with ``X''
++ ** .dt %|X .dd pad to the end of the line with ``X''
++ ** .dt %*X .dd soft-fill with character ``X'' as pad
++ ** .de
++ ** .pp
++ ** * = Can be optionally printed if nonzero
++ ** @ = Only applicable to the current folder
++ */
++ { "sidebar_indent_string", DT_STR, R_BOTH, UL &SidebarIndentString, UL " " },
++ /*
++ ** .pp
++ ** This specifies the string that is used to indent mailboxes in the sidebar.
++ ** It defaults to two spaces.
++ ** .pp
++ ** \fBSee also:\fP $$sidebar_short_path, $$sidebar_folder_indent, $$sidebar_delim_chars.
++ */
++ { "sidebar_new_mail_only", DT_BOOL, R_BOTH, OPTSIDEBARNEWMAILONLY, 0 },
++ /*
++ ** .pp
++ ** When set, the sidebar will only display mailboxes containing new, or
++ ** flagged, mail.
++ ** .pp
++ ** \fBSee also:\fP $sidebar_whitelist.
++ */
++ { "sidebar_next_new_wrap", DT_BOOL, R_BOTH, UL OPTSIDEBARNEXTNEWWRAP, 0 },
++ /*
++ ** .pp
++ ** When set, the \fC\fP command will not stop and the end of
++ ** the list of mailboxes, but wrap around to the beginning. The
++ ** \fC\fP command is similarly affected, wrapping around to
++ ** the end of the list.
++ */
++ { "sidebar_refresh_time", DT_NUM, R_BOTH, UL &SidebarRefreshTime, 60 },
++ /*
++ ** .pp
++ ** Set sidebar_refresh_time to the minimum number of seconds between refreshes.
++ ** This will reduce network traffic.
++ ** .pp
++ ** \fBNote:\fP Set to 0 to disable refreshing.
++ */
++ { "sidebar_short_path", DT_BOOL, R_BOTH, OPTSIDEBARSHORTPATH, 0 },
++ /*
++ ** .pp
++ ** By default the sidebar will show the mailbox's path, relative to the
++ ** $$folder variable. Setting \fCsidebar_shortpath=yes\fP will shorten the
++ ** names relative to the previous name. Here's an example:
++ ** .dl
++ ** .dt \fBshortpath=no\fP .dd \fBshortpath=yes\fP .dd \fBshortpath=yes, folderindent=yes, indentstr=".."\fP
++ ** .dt \fCfruit\fP .dd \fCfruit\fP .dd \fCfruit\fP
++ ** .dt \fCfruit.apple\fP .dd \fCapple\fP .dd \fC..apple\fP
++ ** .dt \fCfruit.banana\fP .dd \fCbanana\fP .dd \fC..banana\fP
++ ** .dt \fCfruit.cherry\fP .dd \fCcherry\fP .dd \fC..cherry\fP
++ ** .de
++ ** .pp
++ ** \fBSee also:\fP $$sidebar_delim_chars, $$sidebar_folder_indent, $$sidebar_indent_string.
++ */
++ { "sidebar_sort_method", DT_SORT|DT_SORT_SIDEBAR, R_NONE, UL &SidebarSortMethod, SORT_ORDER },
++ /*
++ ** .pp
++ ** Specifies how to sort entries in the file browser. By default, the
++ ** entries are sorted alphabetically. Valid values:
++ ** .il
++ ** .dd alpha (alphabetically)
++ ** .dd count (all message count)
++ ** .dd date
++ ** .dd desc (description)
++ ** .dd new (new message count)
++ ** .dd size
++ ** .dd unsorted
++ ** .ie
++ ** .pp
++ ** You may optionally use the ``reverse-'' prefix to specify reverse sorting
++ ** order (example: ``\fCset sort_browser=reverse-date\fP'').
+ */
+ { "sidebar_visible", DT_BOOL, R_BOTH, OPTSIDEBAR, 0 },
+ /*
+ ** .pp
-+ ** This specifies whether or not to show sidebar (left-side list of folders).
-+ */
-+ { "sidebar_sort", DT_BOOL, R_BOTH, OPTSIDEBARSORT, 0 },
-+ /*
++ ** This specifies whether or not to show sidebar. The sidebar shows a list of
++ ** all your mailboxes.
+ ** .pp
-+ ** This specifies whether or not to sort the sidebar alphabetically.
++ ** \fBSee also:\fP $$sidebar_format, $$sidebar_width
+ */
+ { "sidebar_width", DT_NUM, R_BOTH, UL &SidebarWidth, 0 },
+ /*
+ ** .pp
-+ ** The width of the sidebar.
++ ** This controls the width of the sidebar. It is measured in screen columns.
++ ** For example: sidebar_width=20 could display 20 ASCII characters, or 10
++ ** Chinese characters.
+ */
- { "pgp_use_gpg_agent", DT_BOOL, R_NONE, OPTUSEGPGAGENT, 0},
++#endif
+ { "sig_dashes", DT_BOOL, R_NONE, OPTSIGDASHES, 1 },
/*
** .pp
-diff --git a/mailbox.h b/mailbox.h
-index 2b2c9a1..000503d 100644
---- a/mailbox.h
-+++ b/mailbox.h
-@@ -27,6 +27,7 @@
+@@ -3652,6 +3794,19 @@
+ { NULL, 0 }
+ };
+
++const struct mapping_t SortSidebarMethods[] = {
++ { "alpha", SORT_PATH },
++ { "count", SORT_COUNT },
++ { "desc", SORT_DESC },
++ { "flagged", SORT_FLAGGED },
++ { "mailbox-order", SORT_ORDER },
++ { "name", SORT_PATH },
++ { "new", SORT_COUNT_NEW },
++ { "path", SORT_PATH },
++ { "unsorted", SORT_ORDER },
++ { NULL, 0 }
++};
++
+
+ /* functions used to parse commands in a rc file */
+
+@@ -3741,6 +3896,9 @@
+ { "send-hook", mutt_parse_hook, M_SENDHOOK },
+ { "send2-hook", mutt_parse_hook, M_SEND2HOOK },
+ { "set", parse_set, 0 },
++#ifdef USE_SIDEBAR
++ { "sidebar_whitelist",parse_list, UL &SidebarWhitelist },
++#endif
+ { "source", parse_source, 0 },
+ { "spam", parse_spam_list, M_SPAM },
+ { "nospam", parse_spam_list, M_NOSPAM },
+diff -urN mutt-1.6.1/keymap.c mutt-1.6.1-sidebar/keymap.c
+--- mutt-1.6.1/keymap.c 2016-06-12 18:43:00.408447684 +0100
++++ mutt-1.6.1-sidebar/keymap.c 2016-06-12 18:43:03.960503075 +0100
+@@ -453,6 +453,9 @@
+ }
+ #endif
+
++ /* update sidebar stats */
++ mutt_buffy_check(0);
++
+ timeout (i * 1000);
+ tmp = mutt_getch();
+ timeout (-1);
+diff -urN mutt-1.6.1/mailbox.h mutt-1.6.1-sidebar/mailbox.h
+--- mutt-1.6.1/mailbox.h 2016-06-12 18:43:00.408447684 +0100
++++ mutt-1.6.1-sidebar/mailbox.h 2016-06-12 18:43:03.960503075 +0100
+@@ -27,6 +27,9 @@
#define M_NEWFOLDER (1<<4) /* create a new folder - same as M_APPEND, but uses
* safe_fopen() for mbox-style folders.
*/
++#ifdef USE_SIDEBAR
+#define M_PEEK (1<<5) /* revert atime back after taking a look (if applicable) */
++#endif
/* mx_open_new_message() */
#define M_ADD_FROM (1<<0) /* add a From_ line */
-diff --git a/mbox.c b/mbox.c
-index 6d3b6bd..fa82eb3 100644
---- a/mbox.c
-+++ b/mbox.c
-@@ -104,6 +104,7 @@ int mmdf_parse_mailbox (CONTEXT *ctx)
+diff -urN mutt-1.6.1/main.c mutt-1.6.1-sidebar/main.c
+--- mutt-1.6.1/main.c 2016-06-12 18:43:00.409447699 +0100
++++ mutt-1.6.1-sidebar/main.c 2016-06-12 18:43:03.961503091 +0100
+@@ -31,6 +31,9 @@
+ #include "url.h"
+ #include "mutt_crypt.h"
+ #include "mutt_idna.h"
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
+
+ #ifdef USE_SASL
+ #include "mutt_sasl.h"
+@@ -485,6 +488,12 @@
+ "-USE_HCACHE "
+ #endif
+
++#ifdef USE_SIDEBAR
++ "+USE_SIDEBAR "
++#else
++ "-USE_SIDEBAR "
++#endif
++
+ );
+
+ #ifdef ISPELL
+@@ -557,7 +566,11 @@
+
+ int main (int argc, char **argv)
+ {
++#ifdef USE_SIDEBAR
++ char folder[PATH_MAX] = "";
++#else
+ char folder[_POSIX_PATH_MAX] = "";
++#endif
+ char *subject = NULL;
+ char *includeFile = NULL;
+ char *draftFile = NULL;
+@@ -828,6 +841,9 @@
+ clear ();
+ mutt_error = mutt_curses_error;
+ mutt_message = mutt_curses_message;
++#ifdef USE_SIDEBAR
++ mutt_sb_init();
++#endif
+ }
+
+ /* Create the Maildir directory if it doesn't exist. */
+@@ -1184,6 +1200,15 @@
+ strfcpy (folder, NONULL(Spoolfile), sizeof (folder));
+ mutt_expand_path (folder, sizeof (folder));
+
++#ifdef USE_SIDEBAR
++ {
++ char tmpfolder[PATH_MAX] = "";
++ strfcpy (tmpfolder, folder, sizeof (tmpfolder));
++ if (!realpath (tmpfolder, folder))
++ strfcpy (folder, tmpfolder, sizeof (tmpfolder));
++ }
++#endif
++
+ mutt_str_replace (&CurrentFolder, folder);
+ mutt_str_replace (&LastFolder, folder);
+
+@@ -1206,6 +1231,9 @@
+ if((Context = mx_open_mailbox (folder, ((flags & M_RO) || option (OPTREADONLY)) ? M_READONLY : 0, NULL))
+ || !explicit_folder)
+ {
++#ifdef USE_SIDEBAR
++ mutt_sb_set_open_buffy (folder);
++#endif
+ mutt_index_menu ();
+ if (Context)
+ FREE (&Context);
+diff -urN mutt-1.6.1/Makefile.am mutt-1.6.1-sidebar/Makefile.am
+--- mutt-1.6.1/Makefile.am 2016-06-12 18:43:00.389447388 +0100
++++ mutt-1.6.1-sidebar/Makefile.am 2016-06-12 18:43:03.944502826 +0100
+@@ -56,7 +56,7 @@
+ mutt_idna.c mutt_sasl.c mutt_socket.c mutt_ssl.c mutt_ssl_gnutls.c \
+ mutt_tunnel.c pgp.c pgpinvoke.c pgpkey.c pgplib.c pgpmicalg.c \
+ pgppacket.c pop.c pop_auth.c pop_lib.c remailer.c resize.c sha1.c \
+- smime.c smtp.c utf8.c wcwidth.c \
++ sidebar.c smime.c smtp.c utf8.c wcwidth.c \
+ bcache.h browser.h hcache.h mbyte.h mutt_idna.h remailer.h url.h
+
+ EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP OPS.CRYPT OPS.SMIME TODO UPDATING \
+@@ -71,7 +71,7 @@
+ mbyte.h lib.h extlib.c pgpewrap.c smime_keys.pl pgplib.h \
+ README.SSL smime.h group.h \
+ muttbug pgppacket.h depcomp ascii.h BEWARE PATCHES patchlist.sh \
+- ChangeLog mkchangelog.sh mutt_idna.h \
++ ChangeLog mkchangelog.sh mutt_idna.h sidebar.h OPS.sidebar \
+ snprintf.c regex.c crypt-gpgme.h hcachever.sh.in sys_socket.h \
+ txt2c.c txt2c.sh version.sh check_sec.sh
+
+@@ -129,9 +129,9 @@
+ keymap_defs.h: $(OPS) $(srcdir)/gen_defs
+ $(srcdir)/gen_defs $(OPS) > keymap_defs.h
+
+-keymap_alldefs.h: $(srcdir)/OPS $(srcdir)/OPS.PGP $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME $(srcdir)/gen_defs
++keymap_alldefs.h: $(srcdir)/OPS $(srcdir)/OPS.SIDEBAR $(srcdir)/OPS.PGP $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME $(srcdir)/gen_defs
+ rm -f $@
+- $(srcdir)/gen_defs $(srcdir)/OPS $(srcdir)/OPS.PGP \
++ $(srcdir)/gen_defs $(srcdir)/OPS $(srcdir)/OPS.SIDEBAR $(srcdir)/OPS.PGP \
+ $(srcdir)/OPS.MIX $(srcdir)/OPS.CRYPT $(srcdir)/OPS.SMIME \
+ > keymap_alldefs.h
+
+diff -urN mutt-1.6.1/mbox.c mutt-1.6.1-sidebar/mbox.c
+--- mutt-1.6.1/mbox.c 2016-06-12 18:43:00.409447699 +0100
++++ mutt-1.6.1-sidebar/mbox.c 2016-06-12 18:43:03.961503091 +0100
+@@ -100,6 +100,9 @@
mutt_perror (ctx->path);
return (-1);
}
++#ifdef USE_SIDEBAR
+ ctx->atime = sb.st_atime;
++#endif
ctx->mtime = sb.st_mtime;
ctx->size = sb.st_size;
-@@ -255,6 +256,7 @@ int mbox_parse_mailbox (CONTEXT *ctx)
+@@ -251,6 +254,9 @@
ctx->size = sb.st_size;
ctx->mtime = sb.st_mtime;
++#ifdef USE_SIDEBAR
+ ctx->atime = sb.st_atime;
++#endif
#ifdef NFS_ATTRIBUTE_HACK
if (sb.st_mtime > sb.st_atime)
-diff --git a/menu.c b/menu.c
-index 27b5f8e..bc3a02f 100644
---- a/menu.c
-+++ b/menu.c
-@@ -24,6 +24,7 @@
+diff -urN mutt-1.6.1/menu.c mutt-1.6.1-sidebar/menu.c
+--- mutt-1.6.1/menu.c 2016-06-12 18:43:00.409447699 +0100
++++ mutt-1.6.1-sidebar/menu.c 2016-06-12 18:43:03.961503091 +0100
+@@ -24,6 +24,9 @@
#include "mutt_curses.h"
#include "mutt_menu.h"
#include "mbyte.h"
++#ifdef USE_SIDEBAR
+#include "sidebar.h"
++#endif
- extern size_t UngetCount;
+ char* SearchBuffers[MENU_MAX];
-@@ -186,7 +187,7 @@ static void menu_pad_string (char *s, size_t n)
+@@ -184,7 +187,7 @@
{
char *scratch = safe_strdup (s);
int shift = option (OPTARROWCURSOR) ? 3 : 0;
@@ -702,15 +2575,17 @@ index 27b5f8e..bc3a02f 100644
mutt_format_string (s, n, cols, cols, FMT_LEFT, ' ', scratch, mutt_strlen (scratch), 1);
s[n - 1] = 0;
-@@ -239,6 +240,7 @@ void menu_redraw_index (MUTTMENU *menu)
+@@ -237,6 +240,9 @@
int do_color;
int attr;
-+ draw_sidebar(1);
++#ifdef USE_SIDEBAR
++ mutt_sb_draw();
++#endif
for (i = menu->top; i < menu->top + menu->pagelen; i++)
{
if (i < menu->max)
-@@ -249,7 +251,7 @@ void menu_redraw_index (MUTTMENU *menu)
+@@ -247,7 +253,7 @@
menu_pad_string (buf, sizeof (buf));
ATTRSET(attr);
@@ -719,16 +2594,19 @@ index 27b5f8e..bc3a02f 100644
do_color = 1;
if (i == menu->current)
-@@ -272,7 +274,7 @@ void menu_redraw_index (MUTTMENU *menu)
+@@ -270,7 +276,11 @@
else
{
NORMAL_COLOR;
-- CLEARLINE(i - menu->top + menu->offset);
++#ifdef USE_SIDEBAR
+ CLEARLINE_WIN(i - menu->top + menu->offset);
++#else
+ CLEARLINE(i - menu->top + menu->offset);
++#endif
}
}
NORMAL_COLOR;
-@@ -289,7 +291,7 @@ void menu_redraw_motion (MUTTMENU *menu)
+@@ -287,7 +297,7 @@
return;
}
@@ -737,7 +2615,7 @@ index 27b5f8e..bc3a02f 100644
ATTRSET(menu->color (menu->oldcurrent));
if (option (OPTARROWCURSOR))
-@@ -301,13 +303,13 @@ void menu_redraw_motion (MUTTMENU *menu)
+@@ -299,13 +309,13 @@
{
menu_make_entry (buf, sizeof (buf), menu, menu->oldcurrent);
menu_pad_string (buf, sizeof (buf));
@@ -753,7 +2631,7 @@ index 27b5f8e..bc3a02f 100644
}
else
{
-@@ -320,7 +322,7 @@ void menu_redraw_motion (MUTTMENU *menu)
+@@ -318,7 +328,7 @@
menu_make_entry (buf, sizeof (buf), menu, menu->current);
menu_pad_string (buf, sizeof (buf));
SETCOLOR(MT_COLOR_INDICATOR);
@@ -762,7 +2640,7 @@ index 27b5f8e..bc3a02f 100644
print_enriched_string (menu->color(menu->current), (unsigned char *) buf, 0);
}
menu->redraw &= REDRAW_STATUS;
-@@ -332,7 +334,7 @@ void menu_redraw_current (MUTTMENU *menu)
+@@ -330,7 +340,7 @@
char buf[LONG_STRING];
int attr = menu->color (menu->current);
@@ -771,7 +2649,7 @@ index 27b5f8e..bc3a02f 100644
menu_make_entry (buf, sizeof (buf), menu, menu->current);
menu_pad_string (buf, sizeof (buf));
-@@ -881,7 +883,7 @@ int mutt_menuLoop (MUTTMENU *menu)
+@@ -873,7 +883,7 @@
if (option (OPTARROWCURSOR))
@@ -780,160 +2658,207 @@ index 27b5f8e..bc3a02f 100644
else if (option (OPTBRAILLEFRIENDLY))
move (menu->current - menu->top + menu->offset, 0);
else
-diff --git a/mh.c b/mh.c
-index 63e12d2..4a84a99 100644
---- a/mh.c
-+++ b/mh.c
-@@ -295,6 +295,28 @@ void mh_buffy(BUFFY *b)
+diff -urN mutt-1.6.1/mh.c mutt-1.6.1-sidebar/mh.c
+--- mutt-1.6.1/mh.c 2016-06-12 18:43:00.410447715 +0100
++++ mutt-1.6.1-sidebar/mh.c 2016-06-12 18:43:03.962503107 +0100
+@@ -295,6 +295,48 @@
mhs_free_sequences (&mhs);
}
-+void mh_buffy_update (const char *path, int *msgcount, int *msg_unread, int *msg_flagged)
++#ifdef USE_SIDEBAR
++/**
++ * mh_buffy_update - Update messages counts for an mh mailbox
++ * @mailbox: BUFFY representing a maildir mailbox
++ *
++ * Read through an mh mailbox and count messages. Save the number of new,
++ * flagged messages and a timestamp for now.
++ */
++void
++mh_buffy_update (BUFFY *mailbox)
+{
+ int i;
+ struct mh_sequences mhs;
-+ memset (&mhs, 0, sizeof (mhs));
+
-+ if (mh_read_sequences (&mhs, path) < 0)
++ if (!mailbox)
+ return;
+
-+ msgcount = 0;
-+ msg_unread = 0;
-+ msg_flagged = 0;
++ if (!option (OPTSIDEBAR))
++ return;
++
++ memset (&mhs, 0, sizeof (mhs));
++
++ if (mh_read_sequences (&mhs, mailbox->path) < 0)
++ return;
++
++ mailbox->msg_count = 0;
++ mailbox->msg_unread = 0;
++ mailbox->msg_flagged = 0;
++
+ for (i = 0; i <= mhs.max; i++)
-+ msgcount++;
-+ if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN) {
-+ msg_unread++;
++ {
++ mailbox->msg_count++;
++ if (mhs_check (&mhs, i) & MH_SEQ_UNSEEN)
++ mailbox->msg_unread++;
++ if (mhs_check (&mhs, i) & MH_SEQ_FLAGGED)
++ mailbox->msg_flagged++;
+ }
-+ if (mhs_check (&mhs, i) & MH_SEQ_FLAGGED)
-+ msg_flagged++;
+ mhs_free_sequences (&mhs);
++ mailbox->sb_last_checked = time (NULL);
+}
++#endif
+
static int mh_mkstemp (CONTEXT * dest, FILE ** fp, char **tgt)
{
int fd;
-diff --git a/mutt.h b/mutt.h
-index 01d47de..5f25406 100644
---- a/mutt.h
-+++ b/mutt.h
-@@ -435,6 +435,8 @@ enum
- OPTSAVEEMPTY,
- OPTSAVENAME,
- OPTSCORE,
-+ OPTSIDEBAR,
-+ OPTSIDEBARSORT,
- OPTSIGDASHES,
- OPTSIGONTOP,
- OPTSORTRE,
-@@ -880,6 +882,7 @@ typedef struct _context
- {
- char *path;
- FILE *fp;
-+ time_t atime;
- time_t mtime;
- off_t size;
- off_t vsize;
-@@ -920,6 +923,7 @@ typedef struct _context
- unsigned int quiet : 1; /* inhibit status messages? */
- unsigned int collapsed : 1; /* are all threads collapsed? */
- unsigned int closing : 1; /* mailbox is being closed */
-+ unsigned int peekonly : 1; /* just taking a glance, revert atime */
-
- /* driver hooks */
- void *data; /* driver specific data */
-diff --git a/mutt_curses.h b/mutt_curses.h
-index f8bc47c..ef9884e 100644
---- a/mutt_curses.h
-+++ b/mutt_curses.h
-@@ -64,6 +64,7 @@
+diff -urN mutt-1.6.1/mutt_curses.h mutt-1.6.1-sidebar/mutt_curses.h
+--- mutt-1.6.1/mutt_curses.h 2016-06-12 18:43:00.410447715 +0100
++++ mutt-1.6.1-sidebar/mutt_curses.h 2016-06-12 18:43:03.962503107 +0100
+@@ -64,6 +64,9 @@
#undef lines
#endif /* lines */
-+#define CLEARLINE_WIN(x) move(x,SidebarWidth), clrtoeol()
++#ifdef USE_SIDEBAR
++#define CLEARLINE_WIN(x) move (x,SidebarWidth), clrtoeol()
++#endif
#define CLEARLINE(x) move(x,0), clrtoeol()
#define CENTERLINE(x,y) move(y, (COLS-strlen(x))/2), addstr(x)
#define BEEP() do { if (option (OPTBEEP)) beep(); } while (0)
-@@ -121,6 +122,8 @@ enum
+@@ -124,6 +127,14 @@
MT_COLOR_UNDERLINE,
MT_COLOR_INDEX,
MT_COLOR_PROMPT,
-+ MT_COLOR_NEW,
++#ifdef USE_SIDEBAR
++ MT_COLOR_DIVIDER,
+ MT_COLOR_FLAGGED,
++ MT_COLOR_HIGHLIGHT,
++ MT_COLOR_NEW,
++ MT_COLOR_SB_INDICATOR,
++ MT_COLOR_SB_SPOOLFILE,
++#endif
MT_COLOR_MAX
};
-diff --git a/muttlib.c b/muttlib.c
-index c1d565f..039e7c3 100644
---- a/muttlib.c
-+++ b/muttlib.c
-@@ -1279,6 +1279,8 @@ void mutt_FormatString (char *dest, /* output buffer */
+@@ -163,12 +174,16 @@
+
+ static inline int mutt_term_width(short wrap)
+ {
++ int cols = COLS;
++#ifdef USE_SIDEBAR
++ cols -= SidebarWidth;
++#endif
+ if (wrap < 0)
+- return COLS > -wrap ? COLS + wrap : COLS;
++ return cols > -wrap ? cols + wrap : cols;
+ else if (wrap)
+- return wrap < COLS ? wrap : COLS;
++ return wrap < cols ? wrap : cols;
+ else
+- return COLS;
++ return cols;
+ }
+
+ extern int *ColorQuote;
+diff -urN mutt-1.6.1/mutt.h mutt-1.6.1-sidebar/mutt.h
+--- mutt-1.6.1/mutt.h 2016-06-12 18:43:00.410447715 +0100
++++ mutt-1.6.1-sidebar/mutt.h 2016-06-12 18:43:03.962503107 +0100
+@@ -428,6 +428,13 @@
+ OPTSAVEEMPTY,
+ OPTSAVENAME,
+ OPTSCORE,
++#ifdef USE_SIDEBAR
++ OPTSIDEBAR,
++ OPTSIDEBARFOLDERINDENT,
++ OPTSIDEBARNEWMAILONLY,
++ OPTSIDEBARNEXTNEWWRAP,
++ OPTSIDEBARSHORTPATH,
++#endif
+ OPTSIGDASHES,
+ OPTSIGONTOP,
+ OPTSORTRE,
+@@ -872,6 +879,9 @@
+ {
+ char *path;
+ FILE *fp;
++#ifdef USE_SIDEBAR
++ time_t atime;
++#endif
+ time_t mtime;
+ off_t size;
+ off_t vsize;
+@@ -906,6 +916,9 @@
+ unsigned int quiet : 1; /* inhibit status messages? */
+ unsigned int collapsed : 1; /* are all threads collapsed? */
+ unsigned int closing : 1; /* mailbox is being closed */
++#ifdef USE_SIDEBAR
++ unsigned int peekonly : 1; /* just taking a glance, revert atime */
++#endif
+
+ /* driver hooks */
+ void *data; /* driver specific data */
+diff -urN mutt-1.6.1/muttlib.c mutt-1.6.1-sidebar/muttlib.c
+--- mutt-1.6.1/muttlib.c 2016-06-12 18:43:00.411447731 +0100
++++ mutt-1.6.1-sidebar/muttlib.c 2016-06-12 18:43:03.963503122 +0100
+@@ -1282,7 +1282,7 @@
pl = pw = 1;
/* see if there's room to add content, else ignore */
-+ if ( DrawFullLine )
-+ {
- if ((col < COLS && wlen < destlen) || soft)
+- if ((col < COLS && wlen < destlen) || soft)
++ if ((col < (COLS - SidebarWidth) && (wlen < destlen)) || soft)
{
int pad;
-@@ -1322,6 +1324,52 @@ void mutt_FormatString (char *dest, /* output buffer */
- col += wid;
- src += pl;
- }
-+ }
-+ else
-+ {
-+ if ((col < COLS-SidebarWidth && wlen < destlen) || soft)
-+ {
-+ int pad;
-+
-+ /* get contents after padding */
-+ mutt_FormatString (buf, sizeof (buf), 0, src + pl, callback, data, flags);
-+ len = mutt_strlen (buf);
-+ wid = mutt_strwidth (buf);
-+
-+ /* try to consume as many columns as we can, if we don't have
-+ * memory for that, use as much memory as possible */
+
+@@ -1293,7 +1293,7 @@
+
+ /* try to consume as many columns as we can, if we don't have
+ * memory for that, use as much memory as possible */
+- pad = (COLS - col - wid) / pw;
+ pad = (COLS - SidebarWidth - col - wid) / pw;
-+ if (pad > 0 && wlen + (pad * pl) + len > destlen)
-+ pad = ((signed)(destlen - wlen - len)) / pl;
-+ if (pad > 0)
-+ {
-+ while (pad--)
-+ {
-+ memcpy (wptr, src, pl);
-+ wptr += pl;
-+ wlen += pl;
-+ col += pw;
-+ }
-+ }
-+ else if (soft && pad < 0)
-+ {
-+ /* \0-terminate dest for length computation in mutt_wstr_trunc() */
-+ *wptr = 0;
-+ /* make sure right part is at most as wide as display */
-+ len = mutt_wstr_trunc (buf, destlen, COLS, &wid);
-+ /* truncate left so that right part fits completely in */
-+ wlen = mutt_wstr_trunc (dest, destlen - len, col + pad, &col);
-+ wptr = dest + wlen;
-+ }
-+ if (len + wlen > destlen)
+ if (pad > 0 && wlen + (pad * pl) + len > destlen)
+ pad = ((signed)(destlen - wlen - len)) / pl;
+ if (pad > 0)
+@@ -1312,13 +1312,13 @@
+ /* \0-terminate dest for length computation in mutt_wstr_trunc() */
+ *wptr = 0;
+ /* make sure right part is at most as wide as display */
+- len = mutt_wstr_trunc (buf, destlen, COLS-offset, &wid);
++ len = mutt_wstr_trunc (buf, destlen, COLS - offset - SidebarWidth, &wid);
+ /* truncate left so that right part fits completely in */
+ wlen = mutt_wstr_trunc (dest, destlen - len, col + pad*pw -offset, &col);
+ wptr = dest + wlen;
+ }
+ if (len + wlen > destlen)
+- len = mutt_wstr_trunc (buf, destlen - wlen, COLS - col, NULL);
+ len = mutt_wstr_trunc (buf, destlen - wlen, COLS - SidebarWidth - col, NULL);
-+ memcpy (wptr, buf, len);
-+ wptr += len;
-+ wlen += len;
-+ col += wid;
-+ src += pl;
-+ }
-+ }
- break; /* skip rest of input */
- }
- else if (ch == '|')
-diff --git a/mx.c b/mx.c
-index 0a1a80e..e80b8ff 100644
---- a/mx.c
-+++ b/mx.c
-@@ -595,6 +595,7 @@ static int mx_open_mailbox_append (CONTEXT *ctx, int flags)
+ memcpy (wptr, buf, len);
+ wptr += len;
+ wlen += len;
+diff -urN mutt-1.6.1/mutt_menu.h mutt-1.6.1-sidebar/mutt_menu.h
+--- mutt-1.6.1/mutt_menu.h 2016-06-12 18:43:00.410447715 +0100
++++ mutt-1.6.1-sidebar/mutt_menu.h 2016-06-12 18:43:03.962503107 +0100
+@@ -34,6 +34,9 @@
+ #define REDRAW_FULL (1<<5)
+ #define REDRAW_BODY (1<<6)
+ #define REDRAW_SIGWINCH (1<<7)
++#ifdef USE_SIDEBAR
++#define REDRAW_SIDEBAR (1<<8)
++#endif
+
+ #define M_MODEFMT "-- Mutt: %s"
+
+diff -urN mutt-1.6.1/mx.c mutt-1.6.1-sidebar/mx.c
+--- mutt-1.6.1/mx.c 2016-06-12 18:43:00.411447731 +0100
++++ mutt-1.6.1-sidebar/mx.c 2016-06-12 18:43:03.963503122 +0100
+@@ -29,6 +29,9 @@
+ #include "copy.h"
+ #include "keymap.h"
+ #include "url.h"
++#ifdef USE_SIDEBAR
++#include "sidebar.h"
++#endif
+
+ #ifdef USE_IMAP
+ #include "imap.h"
+@@ -580,6 +583,7 @@
* M_APPEND open mailbox for appending
* M_READONLY open mailbox in read-only mode
* M_QUIET only print error messages
@@ -941,70 +2866,128 @@ index 0a1a80e..e80b8ff 100644
* ctx if non-null, context struct to use
*/
CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
-@@ -617,6 +618,8 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
+@@ -602,6 +606,10 @@
ctx->quiet = 1;
if (flags & M_READONLY)
ctx->readonly = 1;
++#ifdef USE_SIDEBAR
+ if (flags & M_PEEK)
+ ctx->peekonly = 1;
++#endif
if (flags & (M_APPEND|M_NEWFOLDER))
{
-@@ -721,9 +724,21 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx)
- void mx_fastclose_mailbox (CONTEXT *ctx)
- {
- int i;
-+#ifndef BUFFY_SIZE
-+ struct utimbuf ut;
-+#endif
-
+@@ -705,8 +713,21 @@
if(!ctx)
return;
-+#ifndef BUFFY_SIZE
+
++#ifdef USE_SIDEBAR
+ /* fix up the times so buffy won't get confused */
-+ if (ctx->peekonly && ctx->path && ctx->mtime > ctx->atime)
-+ {
-+ ut.actime = ctx->atime;
++ struct utimbuf ut;
++ if (ctx->peekonly && ctx->path && (ctx->mtime > ctx->atime)) {
++ ut.actime = ctx->atime;
+ ut.modtime = ctx->mtime;
-+ utime (ctx->path, &ut);
++ utime (ctx->path, &ut);
+ }
+#endif
-
++
/* never announce that a mailbox we've just left has new mail. #3290
* XXX: really belongs in mx_close_mailbox, but this is a nice hook point */
-diff --git a/mx.h b/mx.h
-index 2ef4ec7..4aabadf 100644
---- a/mx.h
-+++ b/mx.h
-@@ -60,6 +60,7 @@ void mbox_reset_atime (CONTEXT *, struct stat *);
++#ifdef USE_SIDEBAR
++ if (!ctx->peekonly)
++#endif
+ mutt_buffy_setnotified(ctx->path);
+
+ if (ctx->mx_close)
+@@ -812,6 +833,12 @@
+ if (!ctx->hdrs[i]->deleted && ctx->hdrs[i]->read
+ && !(ctx->hdrs[i]->flagged && option (OPTKEEPFLAGGED)))
+ read_msgs++;
++#ifdef USE_SIDEBAR
++ if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->read)
++ ctx->unread--;
++ if (ctx->hdrs[i]->deleted && ctx->hdrs[i]->flagged)
++ ctx->flagged--;
++#endif
+ }
+
+ if (read_msgs && quadoption (OPT_MOVE) != M_NO)
+@@ -981,6 +1008,11 @@
+ !mutt_is_spool(ctx->path) && !option (OPTSAVEEMPTY))
+ mx_unlink_empty (ctx->path);
+
++#ifdef USE_SIDEBAR
++ ctx->msgcount -= ctx->deleted;
++ mutt_sb_set_buffystats (ctx);
++#endif
++
+ mx_fastclose_mailbox (ctx);
+
+ return 0;
+diff -urN mutt-1.6.1/mx.h mutt-1.6.1-sidebar/mx.h
+--- mutt-1.6.1/mx.h 2016-06-12 18:43:00.411447731 +0100
++++ mutt-1.6.1-sidebar/mx.h 2016-06-12 18:43:03.963503122 +0100
+@@ -26,6 +26,7 @@
+ #define _MX_H
+
+ #include "mailbox.h"
++#include "buffy.h"
+
+ /* supported mailbox formats */
+ enum
+@@ -57,6 +58,9 @@
int mh_read_dir (CONTEXT *, const char *);
int mh_sync_mailbox (CONTEXT *, int *);
int mh_check_mailbox (CONTEXT *, int *);
-+void mh_buffy_update (const char *, int *, int *, int *);
++#ifdef USE_SIDEBAR
++void mh_buffy_update (BUFFY *mailbox);
++#endif
int mh_check_empty (const char *);
int maildir_read_dir (CONTEXT *);
-diff --git a/pager.c b/pager.c
-index c99f1e4..5cfcb75 100644
---- a/pager.c
-+++ b/pager.c
-@@ -29,6 +29,7 @@
+diff -urN mutt-1.6.1/OPS.SIDEBAR mutt-1.6.1-sidebar/OPS.SIDEBAR
+--- mutt-1.6.1/OPS.SIDEBAR 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/OPS.SIDEBAR 2016-06-12 18:43:03.944502826 +0100
+@@ -0,0 +1,8 @@
++OP_SIDEBAR_NEXT "Move the highlight to next mailbox"
++OP_SIDEBAR_NEXT_NEW "Move the highlight to next mailbox with new mail"
++OP_SIDEBAR_OPEN "Open highlighted mailbox"
++OP_SIDEBAR_PAGE_DOWN "Scroll the Sidebar down 1 page"
++OP_SIDEBAR_PAGE_UP "Scroll the Sidebar up 1 page"
++OP_SIDEBAR_PREV "Move the highlight to previous mailbox"
++OP_SIDEBAR_PREV_NEW "Move the highlight to previous mailbox with new mail"
++OP_SIDEBAR_TOGGLE_VISIBLE "Make the Sidebar (in)visible"
+diff -urN mutt-1.6.1/pager.c mutt-1.6.1-sidebar/pager.c
+--- mutt-1.6.1/pager.c 2016-06-12 18:43:00.412447746 +0100
++++ mutt-1.6.1-sidebar/pager.c 2016-06-12 18:43:03.964503138 +0100
+@@ -29,6 +29,9 @@
#include "pager.h"
#include "attach.h"
#include "mbyte.h"
++#ifdef USE_SIDEBAR
+#include "sidebar.h"
++#endif
#include "mutt_crypt.h"
-@@ -1095,6 +1096,7 @@ static int format_line (struct line_t **lineInfo, int n, unsigned char *buf,
- wchar_t wc;
- mbstate_t mbstate;
- int wrap_cols = mutt_term_width ((flags & M_PAGER_NOWRAP) ? 0 : Wrap);
-+ wrap_cols -= SidebarWidth;
+@@ -1491,7 +1494,7 @@
+ * a newline (grr!).
+ */
+ #ifndef USE_SLANG_CURSES
+- if (col < COLS)
++ if (col < (COLS - SidebarWidth))
+ #endif
+ addch ('\n');
- if (check_attachment_marker ((char *)buf) == 0)
- wrap_cols = COLS;
-@@ -1746,7 +1748,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1573,6 +1576,7 @@
+
+ int bodyoffset = 1; /* offset of first line of real text */
+ int statusoffset = 0; /* offset for the status bar */
++ int statuswidth = COLS;
+ int helpoffset = LINES - 2; /* offset for the help bar. */
+ int bodylen = LINES - 2 - bodyoffset; /* length of displayable area */
+
+@@ -1747,7 +1751,7 @@
if ((redraw & REDRAW_BODY) || topline != oldtopline)
{
do {
@@ -1013,465 +2996,1455 @@ index c99f1e4..5cfcb75 100644
curline = oldtopline = topline;
lines = 0;
force_redraw = 0;
-@@ -1759,6 +1761,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1760,6 +1764,9 @@
&QuoteList, &q_level, &force_redraw, &SearchRE) > 0)
lines++;
curline++;
-+ move(lines + bodyoffset, SidebarWidth);
++#ifdef USE_SIDEBAR
++ move (lines + bodyoffset, SidebarWidth);
++#endif
}
last_offset = lineInfo[curline].offset;
} while (force_redraw);
-@@ -1771,6 +1774,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1772,6 +1779,9 @@
addch ('~');
addch ('\n');
lines++;
-+ move(lines + bodyoffset, SidebarWidth);
++#ifdef USE_SIDEBAR
++ move (lines + bodyoffset, SidebarWidth);
++#endif
}
NORMAL_COLOR;
-@@ -1794,22 +1798,22 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+@@ -1789,29 +1799,49 @@
+ hfi.ctx = Context;
+ hfi.pager_progress = pager_progress_str;
+
++#ifdef USE_SIDEBAR
++ statuswidth = COLS;
++ if (option (OPTSTATUSONTOP) && (PagerIndexLines > 0))
++ statuswidth -= SidebarWidth;
++#endif
++
+ if (last_pos < sb.st_size - 1)
+ snprintf(pager_progress_str, sizeof(pager_progress_str), OFF_T_FMT "%%", (100 * last_offset / sb.st_size));
+ else
strfcpy(pager_progress_str, (topline == 0) ? "all" : "end", sizeof(pager_progress_str));
/* print out the pager status bar */
- move (statusoffset, 0);
+ move (statusoffset, SidebarWidth);
SETCOLOR (MT_COLOR_STATUS);
++#ifdef USE_SIDEBAR
++ short sw = SidebarWidth;
++ if (option (OPTSTATUSONTOP) && PagerIndexLines > 0) {
++ CLEARLINE_WIN (statusoffset);
++ } else {
++ CLEARLINE (statusoffset);
++ /* Temporarily lie about the sidebar width */
++ SidebarWidth = 0;
++ }
++#endif
if (IsHeader (extra) || IsMsgAttach (extra))
{
- size_t l1 = COLS * MB_LEN_MAX;
-+ size_t l1 = (COLS-SidebarWidth) * MB_LEN_MAX;
++ size_t l1 = statuswidth * MB_LEN_MAX;
size_t l2 = sizeof (buffer);
hfi.hdr = (IsHeader (extra)) ? extra->hdr : extra->bdy->hdr;
mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, NONULL (PagerFmt), &hfi, M_FORMAT_MAKEPRINT);
- mutt_paddstr (COLS, buffer);
-+ mutt_paddstr (COLS-SidebarWidth, buffer);
++ mutt_paddstr (statuswidth, buffer);
}
else
{
char bn[STRING];
snprintf (bn, sizeof (bn), "%s (%s)", banner, pager_progress_str);
- mutt_paddstr (COLS, bn);
-+ mutt_paddstr (COLS-SidebarWidth, bn);
++ mutt_paddstr (statuswidth, bn);
}
++#ifdef USE_SIDEBAR
++ if (!option (OPTSTATUSONTOP) || PagerIndexLines == 0)
++ SidebarWidth = sw; /* Restore the sidebar width */
++#endif
NORMAL_COLOR;
if (option(OPTTSENABLED) && TSSupported)
-@@ -1826,16 +1830,21 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra)
+ {
+@@ -1827,16 +1857,26 @@
/* redraw the pager_index indicator, because the
* flags for this message might have changed. */
menu_redraw_current (index);
-+ draw_sidebar(MENU_PAGER);
++#ifdef USE_SIDEBAR
++ mutt_sb_draw();
++#endif
/* print out the index status bar */
menu_status_line (buffer, sizeof (buffer), index, NONULL(Status));
- move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), 0);
-+ move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), SidebarWidth);
++ move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)),
++ (option(OPTSTATUSONTOP) ? 0: SidebarWidth));
SETCOLOR (MT_COLOR_STATUS);
- mutt_paddstr (COLS, buffer);
-+ mutt_paddstr (COLS-SidebarWidth, buffer);
++ mutt_paddstr (COLS - (option(OPTSTATUSONTOP) ? 0 : SidebarWidth), buffer);
NORMAL_COLOR;
}
++#ifdef USE_SIDEBAR
+ /* if we're not using the index, update every time */
-+ if ( index == 0 )
-+ draw_sidebar(MENU_PAGER);
++ if (index == 0)
++ mutt_sb_draw();
++#endif
+
redraw = 0;
if (option(OPTBRAILLEFRIENDLY)) {
-@@ -2776,6 +2785,13 @@ search_next:
+@@ -2498,8 +2538,12 @@
+ ch = 0;
+ }
+
+- if (option (OPTFORCEREDRAWPAGER))
++ if (option (OPTFORCEREDRAWPAGER)) {
+ redraw = REDRAW_FULL;
++#ifdef USE_SIDEBAR
++ mutt_sb_draw();
++#endif
++ }
+ unset_option (OPTFORCEREDRAWINDEX);
+ unset_option (OPTFORCEREDRAWPAGER);
+ break;
+@@ -2777,6 +2821,22 @@
mutt_what_key ();
break;
-+ case OP_SIDEBAR_SCROLL_UP:
-+ case OP_SIDEBAR_SCROLL_DOWN:
++#ifdef USE_SIDEBAR
+ case OP_SIDEBAR_NEXT:
++ case OP_SIDEBAR_NEXT_NEW:
++ case OP_SIDEBAR_PAGE_DOWN:
++ case OP_SIDEBAR_PAGE_UP:
+ case OP_SIDEBAR_PREV:
-+ scroll_sidebar(ch, MENU_PAGER);
-+ break;
++ case OP_SIDEBAR_PREV_NEW:
++ mutt_sb_change_mailbox (ch);
++ break;
++
++ case OP_SIDEBAR_TOGGLE_VISIBLE:
++ toggle_option (OPTSIDEBAR);
++ redraw = REDRAW_FULL;
++ break;
++#endif
+
default:
ch = -1;
break;
-diff --git a/sidebar.c b/sidebar.c
-new file mode 100644
-index 0000000..6098c2a
---- /dev/null
-+++ b/sidebar.c
-@@ -0,0 +1,333 @@
-+/*
-+ * Copyright (C) ????-2004 Justin Hibbits
+diff -urN mutt-1.6.1/PATCHES mutt-1.6.1-sidebar/PATCHES
+--- mutt-1.6.1/PATCHES 2016-06-12 18:43:00.395447481 +0100
++++ mutt-1.6.1-sidebar/PATCHES 2016-06-12 18:43:03.949502904 +0100
+@@ -0,0 +1 @@
++patch-sidebar-neo-20160612
+diff -urN mutt-1.6.1/README.sidebar mutt-1.6.1-sidebar/README.sidebar
+--- mutt-1.6.1/README.sidebar 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/README.sidebar 2016-06-12 18:43:03.792500456 +0100
+@@ -0,0 +1,145 @@
++Sidebar Patch
++=============
++
++ Overview of mailboxes
++
++ NOTES:
++
++ If you haven't used the sidebar before, you might like to read the
++ Sidebar Introduction:
++
++ http://www.neomutt.org/sidebar-intro.html
++
++ If you have used an older version of the Sidebar, please note that some
++ of the configuration has changed.
++
++ http://www.neomutt.org/sidebar-intro.html#intro-sidebar-config-changes
++
++Patch
++-----
++
++ To check if Mutt supports "Sidebar", look for "+USE_SIDEBAR" in the mutt
++ version.
++
++ Dependencies
++ * mutt-1.6.1
++
++Introduction
++------------
++
++ The Sidebar shows a list of all your mailboxes. The list can be turned on
++ and off, it can be themed and the list style can be configured.
++
++ This part of the manual is a reference guide. If you want a simple
++ introduction with examples see the Sidebar Howto. If you just want to get
++ started, you could use the sample Sidebar muttrc.
++
++ This version of Sidebar is based on Terry Chan's [2015-11-11
++ release](http://www.lunar-linux.org/mutt-sidebar/). It contains many new
++ features, lots of bugfixes.
++
++Variables
++---------
++
++ Sidebar Variables
++
++ | Name | Type | Default |
++ |-------------------------|---------|-----------------------------|
++ | 'sidebar_delim_chars' | string | '/.' |
++ | 'sidebar_divider_char' | string | '|' |
++ | 'sidebar_folder_indent' | boolean | 'no' |
++ | 'sidebar_format' | string | '%B%?F? [%F]?%* %?N?%N/?%S' |
++ | 'sidebar_indent_string' | string | ' ' (two spaces) |
++ | 'sidebar_new_mail_only' | boolean | 'no' |
++ | 'sidebar_next_new_wrap' | boolean | 'no' |
++ | 'sidebar_refresh_time' | number | '60' |
++ | 'sidebar_short_path' | boolean | 'no' |
++ | 'sidebar_sort_method' | enum | 'SORT_ORDER' |
++ | 'sidebar_visible' | boolean | 'no' |
++ | 'sidebar_whitelist' | list | (empty) |
++ | 'sidebar_width' | number | '20' |
++
++Functions
++---------
++
++ Sidebar Functions
++
++ Sidebar adds the following functions to Mutt. By default, none of them are
++ bound to keys.
++
++ | Menus | Function | Description |
++ |-------------|----------------------------|------------------------------------------------------|
++ | index,pager | '' | Move the highlight to next mailbox |
++ | index,pager | '' | Move the highlight to next mailbox with new mail |
++ | index,pager | '' | Open highlighted mailbox |
++ | index,pager | '' | Scroll the Sidebar down 1 page |
++ | index,pager | '' | Scroll the Sidebar up 1 page |
++ | index,pager | '' | Move the highlight to previous mailbox |
++ | index,pager | '' | Move the highlight to previous mailbox with new mail |
++ | index,pager | '' | Make the Sidebar (in)visible |
++
++Commands
++--------
++
++ sidebar_whitelist mailbox [ mailbox... ]
++
++Colors
++------
++
++ Sidebar Colors
++
++ | Name | Default Color | Description |
++ |---------------------|------------------|------------------------------------------------------------------|
++ | 'sidebar_divider' | default | The dividing line between the Sidebar and the Index/Pager panels |
++ | 'sidebar_flagged' | default | Mailboxes containing flagged mail |
++ | 'sidebar_highlight' | underline | Cursor to select a mailbox |
++ | 'sidebar_indicator' | mutt 'indicator' | The mailbox open in the Index panel |
++ | 'sidebar_new' | default | Mailboxes containing new mail |
++ | 'sidebar_spoolfile' | default | Mailbox that receives incoming mail |
++
++ If the sidebar_indicator color isn't set, then the default Mutt indicator
++ color will be used (the color used in the index panel).
++
++Sort
++----
++
++ Sidebar Sort
++
++ | Sort | Description |
++ |------------|----------------------------|
++ | 'alpha' | Alphabetically by path |
++ | 'count' | Total number of messages |
++ | 'flagged' | Number of flagged messages |
++ | 'name' | Alphabetically by path |
++ | 'new' | Number of new messages |
++ | 'path' | Alphabetically by path |
++ | 'unsorted' | Do not resort the paths |
++
++See Also
++--------
++
++ * Regular Expressions
++ * Patterns
++ * Color command
++ * notmuch patch
++
++Known Bugs
++----------
++
++ Unsorted isn't
++
++Credits
++-------
++
++ * Justin Hibbits
++ * Thomer M. Gil
++ * David Sterba
++ * Evgeni Golov
++ * Fabian Groffen
++ * Jason DeTiberus
++ * Stefan Assmann
++ * Steve Kemp
++ * Terry Chan
++ * Tyler Earnest
++ * Richard Russon
++
+diff -urN mutt-1.6.1/sidebar.c mutt-1.6.1-sidebar/sidebar.c
+--- mutt-1.6.1/sidebar.c 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/sidebar.c 2016-06-14 18:46:00.000000000 +0100
+@@ -0,0 +1,1090 @@
++/* Copyright (C) 2004 Justin Hibbits
+ * Copyright (C) 2004 Thomer M. Gil
-+ *
++ * Copyright (C) 2015-2016 Richard Russon
++ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
-+ *
++ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
-+ *
++ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
-+ */
-+
++ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "mutt.h"
-+#include "mutt_menu.h"
-+#include "mutt_curses.h"
-+#include "sidebar.h"
+#include "buffy.h"
-+#include
+#include "keymap.h"
-+#include
++#include "mutt_curses.h"
++#include "mutt_menu.h"
++#include "sort.h"
+
-+/*BUFFY *CurBuffy = 0;*/
-+static BUFFY *TopBuffy = 0;
-+static BUFFY *BottomBuffy = 0;
-+static int known_lines = 0;
++/* Previous values for some sidebar config */
++static short OldVisible; /* sidebar_visible */
++static short OldWidth; /* sidebar_width */
++static short PreviousSort; /* sidebar_sort_method */
++static time_t LastRefresh; /* Time of last refresh */
+
-+static int quick_log10(int n)
++/* Keep track of various BUFFYs */
++static BUFFY *TopBuffy; /* First mailbox visible in sidebar */
++static BUFFY *OpnBuffy; /* Current (open) mailbox */
++static BUFFY *HilBuffy; /* Highlighted mailbox */
++static BUFFY *BotBuffy; /* Last mailbox visible in sidebar */
++static BUFFY *Outgoing; /* Last mailbox in the linked list */
++
++/**
++ * struct sidebar_entry - Info about folders in the sidebar
++ *
++ * Used in the mutt_FormatString callback
++ */
++struct sidebar_entry
+{
-+ char string[32];
-+ sprintf(string, "%d", n);
-+ return strlen(string);
++ char box[STRING];
++ BUFFY *buffy;
++};
++
++
++/**
++ * find_next_new - Find the next folder that contains new mail
++ * @wrap: Wrap around to the beginning if the end is reached
++ *
++ * Search down the list of mail folders for one containing new mail.
++ *
++ * Returns:
++ * BUFFY*: Success
++ * NULL: Failure
++ */
++static BUFFY *find_next_new (int wrap)
++{
++ BUFFY *b = HilBuffy;
++ if (!b)
++ return NULL;
++
++ do
++ {
++ b = b->next;
++ if (!b && wrap)
++ b = Incoming;
++ if (!b || (b == HilBuffy))
++ break;
++ if (b->msg_unread > 0)
++ return b;
++ } while (b);
++
++ return NULL;
+}
+
-+void calc_boundaries (int menu)
++/**
++ * find_prev_new - Find the previous folder that contains new mail
++ * @wrap: Wrap around to the beginning if the end is reached
++ *
++ * Search up the list of mail folders for one containing new mail.
++ *
++ * Returns:
++ * BUFFY*: Success
++ * NULL: Failure
++ */
++static BUFFY *find_prev_new (int wrap)
+{
-+ BUFFY *tmp = Incoming;
++ BUFFY *b = HilBuffy;
++ if (!b)
++ return NULL;
+
-+ if ( known_lines != LINES ) {
-+ TopBuffy = BottomBuffy = 0;
-+ known_lines = LINES;
-+ }
-+ for ( ; tmp->next != 0; tmp = tmp->next )
-+ tmp->next->prev = tmp;
++ do
++ {
++ b = b->prev;
++ if (!b && wrap)
++ b = Outgoing;
++ if (!b || (b == HilBuffy))
++ break;
++ if (b->msg_unread > 0)
++ return b;
++ } while (b);
+
-+ if ( TopBuffy == 0 && BottomBuffy == 0 )
-+ TopBuffy = Incoming;
-+ if ( BottomBuffy == 0 ) {
-+ int count = LINES - 2 - (menu != MENU_PAGER || option(OPTSTATUSONTOP));
-+ BottomBuffy = TopBuffy;
-+ while ( --count && BottomBuffy->next )
-+ BottomBuffy = BottomBuffy->next;
-+ }
-+ else if ( TopBuffy == CurBuffy->next ) {
-+ int count = LINES - 2 - (menu != MENU_PAGER);
-+ BottomBuffy = CurBuffy;
-+ tmp = BottomBuffy;
-+ while ( --count && tmp->prev)
-+ tmp = tmp->prev;
-+ TopBuffy = tmp;
-+ }
-+ else if ( BottomBuffy == CurBuffy->prev ) {
-+ int count = LINES - 2 - (menu != MENU_PAGER);
-+ TopBuffy = CurBuffy;
-+ tmp = TopBuffy;
-+ while ( --count && tmp->next )
-+ tmp = tmp->next;
-+ BottomBuffy = tmp;
-+ }
++ return NULL;
+}
+
-+char *make_sidebar_entry(char *box, int size, int new, int flagged)
++/**
++ * cb_format_str - Create the string to show in the sidebar
++ * @dest: Buffer in which to save string
++ * @destlen: Buffer length
++ * @col: Starting column, UNUSED
++ * @op: printf-like operator, e.g. 'B'
++ * @src: printf-like format string
++ * @prefix: Field formatting string, UNUSED
++ * @ifstring: If condition is met, display this string
++ * @elsestring: Otherwise, display this string
++ * @data: Pointer to our sidebar_entry
++ * @flags: Format flags, e.g. M_FORMAT_OPTIONAL
++ *
++ * cb_format_str is a callback function for mutt_FormatString. It understands
++ * five operators. '%B' : Mailbox name, '%F' : Number of flagged messages,
++ * '%N' : Number of new messages, '%S' : Size (total number of messages),
++ * '%!' : Icon denoting number of flagged messages.
++ *
++ * Returns: src (unchanged)
++ */
++static const char *cb_format_str(char *dest, size_t destlen, size_t col, char op,
++ const char *src, const char *prefix, const char *ifstring,
++ const char *elsestring, unsigned long data, format_flag flags)
+{
-+ static char *entry = 0;
-+ char *c;
-+ int i = 0;
-+ int delim_len = strlen(SidebarDelim);
++ struct sidebar_entry *sbe = (struct sidebar_entry *) data;
++ unsigned int optional;
++ char fmt[STRING];
+
-+ c = realloc(entry, SidebarWidth - delim_len + 2);
-+ if ( c ) entry = c;
-+ entry[SidebarWidth - delim_len + 1] = 0;
-+ for (; i < SidebarWidth - delim_len + 1; entry[i++] = ' ' );
-+ i = strlen(box);
-+ strncpy( entry, box, i < (SidebarWidth - delim_len + 1) ? i : (SidebarWidth - delim_len + 1) );
++ if (!sbe || !dest)
++ return src;
+
-+ if (size == -1)
-+ sprintf(entry + SidebarWidth - delim_len - 3, "?");
-+ else if ( new ) {
-+ if (flagged > 0) {
-+ sprintf(
-+ entry + SidebarWidth - delim_len - 5 - quick_log10(size) - quick_log10(new) - quick_log10(flagged),
-+ "% d(%d)[%d]", size, new, flagged);
-+ } else {
-+ sprintf(
-+ entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(new),
-+ "% d(%d)", size, new);
-+ }
-+ } else if (flagged > 0) {
-+ sprintf( entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(flagged), "% d[%d]", size, flagged);
-+ } else {
-+ sprintf( entry + SidebarWidth - delim_len - 1 - quick_log10(size), "% d", size);
-+ }
-+ return entry;
++ dest[0] = 0; /* Just in case there's nothing to do */
++
++ BUFFY *b = sbe->buffy;
++ if (!b)
++ return src;
++
++ int c = Context && (mutt_strcmp (Context->path, b->path) == 0);
++
++ optional = flags & M_FORMAT_OPTIONAL;
++
++ switch (op)
++ {
++ case 'B':
++ mutt_format_s (dest, destlen, prefix, sbe->box);
++ break;
++
++ case 'd':
++ if (!optional)
++ {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, c ? Context->deleted : 0);
++ }
++ else if ((c && Context->deleted == 0) || !c)
++ optional = 0;
++ break;
++
++ case 'F':
++ if (!optional)
++ {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, b->msg_flagged);
++ }
++ else if (b->msg_flagged == 0)
++ optional = 0;
++ break;
++
++ case 'L':
++ if (!optional)
++ {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, c ? Context->vcount : b->msg_count);
++ }
++ else if ((c && Context->vcount == b->msg_count) || !c)
++ optional = 0;
++ break;
++
++ case 'N':
++ if (!optional)
++ {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, b->msg_unread);
++ }
++ else if (b->msg_unread == 0)
++ optional = 0;
++ break;
++
++ case 'S':
++ if (!optional)
++ {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, b->msg_count);
++ }
++ else if (b->msg_count == 0)
++ optional = 0;
++ break;
++
++ case 't':
++ if (!optional)
++ {
++ snprintf (fmt, sizeof (fmt), "%%%sd", prefix);
++ snprintf (dest, destlen, fmt, c ? Context->tagged : 0);
++ }
++ else if ((c && Context->tagged == 0) || !c)
++ optional = 0;
++ break;
++
++ case '!':
++ if (b->msg_flagged == 0)
++ mutt_format_s (dest, destlen, prefix, "");
++ else if (b->msg_flagged == 1)
++ mutt_format_s (dest, destlen, prefix, "!");
++ else if (b->msg_flagged == 2)
++ mutt_format_s (dest, destlen, prefix, "!!");
++ else
++ {
++ snprintf (fmt, sizeof (fmt), "%d!", b->msg_flagged);
++ mutt_format_s (dest, destlen, prefix, fmt);
++ }
++ break;
++ }
++
++ if (optional)
++ mutt_FormatString (dest, destlen, col, ifstring, cb_format_str, (unsigned long) sbe, flags);
++ else if (flags & M_FORMAT_OPTIONAL)
++ mutt_FormatString (dest, destlen, col, elsestring, cb_format_str, (unsigned long) sbe, flags);
++
++ /* We return the format string, unchanged */
++ return src;
+}
+
-+void set_curbuffy(char buf[LONG_STRING])
++/**
++ * make_sidebar_entry - Turn mailbox data into a sidebar string
++ * @buf: Buffer in which to save string
++ * @buflen: Buffer length
++ * @width: Desired width in screen cells
++ * @box: Mailbox name
++ * @size: Size (total number of messages)
++ * @new: Number of new messages
++ * @flagged: Number of flagged messages
++ *
++ * Take all the relevant mailbox data and the desired screen width and then get
++ * mutt_FormatString to do the actual work. mutt_FormatString will callback to
++ * us using cb_format_str() for the sidebar specific formatting characters.
++ */
++static void make_sidebar_entry (char *buf, unsigned int buflen, int width, char *box,
++ BUFFY *b)
+{
-+ BUFFY* tmp = CurBuffy = Incoming;
++ struct sidebar_entry sbe;
+
-+ if (!Incoming)
++ if (!buf || !box || !b)
+ return;
+
-+ while(1) {
-+ if(!strcmp(tmp->path, buf)) {
-+ CurBuffy = tmp;
-+ break;
-+ }
++ sbe.buffy = b;
++ strfcpy (sbe.box, box, sizeof (sbe.box));
+
-+ if(tmp->next)
-+ tmp = tmp->next;
-+ else
-+ break;
++ /* Temporarily lie about the screen width */
++ int oc = COLS;
++ COLS = width + SidebarWidth;
++ mutt_FormatString (buf, buflen, 0, NONULL(SidebarFormat), cb_format_str, (unsigned long) &sbe, 0);
++ COLS = oc;
++
++ /* Force string to be exactly the right width */
++ int w = mutt_strwidth (buf);
++ int s = strlen (buf);
++ width = MIN(buflen, width);
++ if (w < width)
++ {
++ /* Pad with spaces */
++ memset (buf + s, ' ', width - w);
++ buf[s + width - w] = 0;
++ }
++ else if (w > width)
++ {
++ /* Truncate to fit */
++ int len = mutt_wstr_trunc (buf, buflen, width, NULL);
++ buf[len] = 0;
+ }
+}
+
-+int draw_sidebar(int menu) {
++/**
++ * cb_qsort_buffy - qsort callback to sort BUFFYs
++ * @a: First BUFFY to compare
++ * @b: Second BUFFY to compare
++ *
++ * Compare the paths of two BUFFYs taking the locale into account.
++ *
++ * Returns:
++ * -1: a precedes b
++ * 0: a and b are identical
++ * 1: b precedes a
++ */
++static int cb_qsort_buffy (const void *a, const void *b)
++{
++ const BUFFY *b1 = *(const BUFFY **) a;
++ const BUFFY *b2 = *(const BUFFY **) b;
+
-+ int lines = option(OPTHELP) ? 1 : 0;
-+ BUFFY *tmp;
-+#ifndef USE_SLANG_CURSES
-+ attr_t attrs;
-+#endif
-+ short delim_len = strlen(SidebarDelim);
-+ short color_pair;
++ /* Special case -- move hidden BUFFYs to the end */
++ if (b1->is_hidden != b2->is_hidden)
++ {
++ if (b1->is_hidden)
++ return 1;
++ else
++ return -1;
++ }
+
-+ static bool initialized = false;
-+ static int prev_show_value;
-+ static short saveSidebarWidth;
++ int result = 0;
+
-+ /* initialize first time */
-+ if(!initialized) {
-+ prev_show_value = option(OPTSIDEBAR);
-+ saveSidebarWidth = SidebarWidth;
-+ if(!option(OPTSIDEBAR)) SidebarWidth = 0;
-+ initialized = true;
-+ }
++ switch ((SidebarSortMethod & SORT_MASK))
++ {
++ case SORT_COUNT:
++ result = (b2->msg_count - b1->msg_count);
++ break;
++ case SORT_COUNT_NEW:
++ result = (b2->msg_unread - b1->msg_unread);
++ break;
++ case SORT_FLAGGED:
++ result = (b2->msg_flagged - b1->msg_flagged);
++ break;
++ case SORT_PATH:
++ result = mutt_strcasecmp (b1->path, b2->path);
++ break;
++ }
+
-+ /* save or restore the value SidebarWidth */
-+ if(prev_show_value != option(OPTSIDEBAR)) {
-+ if(prev_show_value && !option(OPTSIDEBAR)) {
-+ saveSidebarWidth = SidebarWidth;
-+ SidebarWidth = 0;
-+ } else if(!prev_show_value && option(OPTSIDEBAR)) {
-+ SidebarWidth = saveSidebarWidth;
-+ }
-+ prev_show_value = option(OPTSIDEBAR);
-+ }
++ if (SidebarSortMethod & SORT_REVERSE)
++ result = -result;
+
++ return result;
++}
+
-+// if ( SidebarWidth == 0 ) return 0;
-+ if (SidebarWidth > 0 && option (OPTSIDEBAR)
-+ && delim_len >= SidebarWidth) {
-+ unset_option (OPTSIDEBAR);
-+ /* saveSidebarWidth = SidebarWidth; */
-+ if (saveSidebarWidth > delim_len) {
-+ SidebarWidth = saveSidebarWidth;
-+ mutt_error (_("Value for sidebar_delim is too long. Disabling sidebar."));
-+ sleep (2);
-+ } else {
-+ SidebarWidth = 0;
-+ mutt_error (_("Value for sidebar_delim is too long. Disabling sidebar. Please set your sidebar_width to a sane value."));
-+ sleep (4); /* the advise to set a sane value should be seen long enough */
-+ }
-+ saveSidebarWidth = 0;
-+ return (0);
-+ }
++/**
++ * buffy_going - Prevent our pointers becoming invalid
++ * @b: BUFFY about to be deleted
++ *
++ * If we receive a delete-notification for a BUFFY, we need to change any
++ * pointers we have to reference a different BUFFY, or set them to NULL.
++ *
++ * We don't update the prev/next pointers, they'll be fixed on the next
++ * call to prepare_sidebar().
++ *
++ * Returns:
++ * A valid alternative BUFFY, or NULL
++ */
++static BUFFY *buffy_going (const BUFFY *b)
++{
++ if (!b)
++ return NULL;
+
-+ if ( SidebarWidth == 0 || !option(OPTSIDEBAR)) {
-+ if (SidebarWidth > 0) {
-+ saveSidebarWidth = SidebarWidth;
-+ SidebarWidth = 0;
-+ }
-+ unset_option(OPTSIDEBAR);
-+ return 0;
++ if (b->prev)
++ {
++ b->prev->next = NULL;
++ }
++
++ if (b->next)
++ {
++ b->next->prev = NULL;
++ return b->next;
++ }
++
++ return b->prev;
++}
++
++/**
++ * update_buffy_visibility - Should a BUFFY be displayed in the sidebar
++ * @arr: array of BUFFYs
++ * @arr_len: number of BUFFYs in array
++ *
++ * For each BUFFY in the array, check whether we should display it.
++ * This is determined by several criteria. If the BUFFY:
++ * is the currently open mailbox
++ * is the currently highlighted mailbox
++ * has unread messages
++ * has flagged messages
++ * is whitelisted
++ */
++static void update_buffy_visibility (BUFFY **arr, int arr_len)
++{
++ if (!arr)
++ return;
++
++ short new_only = option (OPTSIDEBARNEWMAILONLY);
++
++ BUFFY *b;
++ int i;
++ for (i = 0; i < arr_len; i++)
++ {
++ b = arr[i];
++
++ b->is_hidden = 0;
++
++ if (!new_only)
++ continue;
++
++ if ((b == OpnBuffy) || (b->msg_unread > 0) ||
++ (b == HilBuffy) || (b->msg_flagged > 0))
++ continue;
++
++ if (Context && (strcmp (b->path, Context->path) == 0))
++ /* Spool directory */
++ continue;
++
++ if (mutt_find_list (SidebarWhitelist, b->path))
++ /* Explicitly asked to be visible */
++ continue;
++
++ b->is_hidden = 1;
++ }
++}
++
++/**
++ * sort_buffy_array - Sort an array of BUFFY pointers
++ * @arr: array of BUFFYs
++ * @arr_len: number of BUFFYs in array
++ *
++ * Sort an array of BUFFY pointers according to the current sort config
++ * option "sidebar_sort_method". This calls qsort to do the work which calls our
++ * callback function "cb_qsort_buffy".
++ *
++ * Once sorted, the prev/next links will be reconstructed.
++ */
++static void sort_buffy_array (BUFFY **arr, int arr_len)
++{
++ if (!arr)
++ return;
++
++ /* These are the only sort methods we understand */
++ short ssm = (SidebarSortMethod & SORT_MASK);
++ if ((ssm == SORT_COUNT) ||
++ (ssm == SORT_COUNT_NEW) ||
++ (ssm == SORT_DESC) ||
++ (ssm == SORT_FLAGGED) ||
++ (ssm == SORT_PATH))
++ qsort (arr, arr_len, sizeof (*arr), cb_qsort_buffy);
++
++ int i;
++ for (i = 0; i < (arr_len - 1); i++)
++ arr[i]->next = arr[i + 1];
++ arr[arr_len - 1]->next = NULL;
++
++ for (i = 1; i < arr_len; i++)
++ arr[i]->prev = arr[i - 1];
++ arr[0]->prev = NULL;
++}
++
++/**
++ * prepare_sidebar - Prepare the list of BUFFYs for the sidebar display
++ * @page_size: The number of lines on a page
++ *
++ * Before painting the sidebar, we count the BUFFYs, determine which are
++ * visible, sort them and set up our page pointers.
++ *
++ * This is a lot of work to do each refresh, but there are many things that
++ * can change outside of the sidebar that we don't hear about.
++ *
++ * Returns:
++ * 0: No, don't draw the sidebar
++ * 1: Yes, draw the sidebar
++ */
++static int prepare_sidebar (int page_size)
++{
++ BUFFY *b = Incoming;
++ if (!b)
++ return 0;
++
++ int count = 0;
++ for (; b; b = b->next)
++ count++;
++
++ BUFFY **arr = safe_malloc (count * sizeof (*arr));
++
++ int i = 0;
++ for (b = Incoming; b; b = b->next, i++)
++ arr[i] = b;
++
++ update_buffy_visibility (arr, count);
++ sort_buffy_array (arr, count);
++
++ Incoming = arr[0];
++
++ int top_index = 0;
++ int opn_index = -1;
++ int hil_index = -1;
++ int bot_index = -1;
++
++ for (i = 0; i < count; i++)
++ {
++ if (OpnBuffy == arr[i])
++ opn_index = i;
++ if (HilBuffy == arr[i])
++ hil_index = i;
++ }
++
++ if (!HilBuffy || (SidebarSortMethod != PreviousSort))
++ {
++ if (OpnBuffy)
++ {
++ HilBuffy = OpnBuffy;
++ hil_index = opn_index;
++ }
++ else
++ {
++ HilBuffy = arr[0];
++ hil_index = 0;
++ }
++ }
++ if (TopBuffy)
++ top_index = (hil_index / page_size) * page_size;
++ else
++ top_index = hil_index;
++ TopBuffy = arr[top_index];
++
++ bot_index = top_index + page_size - 1;
++ if (bot_index > (count - 1))
++ bot_index = count - 1;
++ BotBuffy = arr[bot_index];
++
++ Outgoing = arr[count - 1];
++
++ PreviousSort = SidebarSortMethod;
++ FREE (&arr);
++ return 1;
++}
++
++/**
++ * visible - Should we display the sidebar?
++ *
++ * After validating the config options "sidebar_visible" and "sidebar_width",
++ * determine whether we should should display the sidebar.
++ *
++ * When not visible, set the global SidebarWidth to 0.
++ *
++ * Returns:
++ * Boolean
++ */
++static short
++visible (void)
++{
++ short new_visible = option (OPTSIDEBAR);
++ short new_width = SidebarWidth;
++
++ if (OldWidth != new_width)
++ {
++ if (new_width > 0)
++ {
++ OldWidth = new_width;
++ }
++ }
++
++ if (OldVisible != new_visible)
++ {
++ if (new_visible)
++ {
++ set_option (OPTSIDEBAR);
++ }
++ else
++ {
++ unset_option (OPTSIDEBAR);
++ }
++ OldVisible = new_visible;
++ }
++ else if (new_width == 0)
++ {
++ unset_option (OPTSIDEBAR);
++ OldVisible = 0;
++ }
++
++ if (!option (OPTSIDEBAR))
++ {
++ SidebarWidth = 0;
++ }
++ else if (new_width == 0)
++ {
++ SidebarWidth = OldWidth;
++ }
++ else
++ {
++ SidebarWidth = new_width;
++ }
++
++ return new_visible;
++}
++
++/**
++ * draw_divider - Draw a line between the sidebar and the rest of mutt
++ * @first_row: Screen line to start (0-based)
++ * @num_rows: Number of rows to fill
++ *
++ * Draw a divider using characters from the config option "sidebar_divider_char".
++ * This can be an ASCII or Unicode character. First we calculate this
++ * characters' width in screen columns, then subtract that from the config
++ * option "sidebar_width".
++ *
++ * Returns:
++ * -1: Error: bad character, etc
++ * 0: Error: 0 width character
++ * n: Success: character occupies n screen columns
++ */
++static int draw_divider (int first_row, int num_rows)
++{
++ /* Calculate the width of the delimiter in screen cells */
++ int delim_len = mutt_strwidth (SidebarDividerChar);
++
++ if (delim_len < 1)
++ return delim_len;
++
++ if ((SidebarWidth + delim_len) > (COLS + 1))
++ return 0;
++
++ if (delim_len > SidebarWidth)
++ return -1;
++
++ SETCOLOR(MT_COLOR_DIVIDER);
++
++ int i;
++ for (i = 0; i < num_rows; i++)
++ {
++ move (first_row + i, SidebarWidth - delim_len);
++ addstr (NONULL(SidebarDividerChar));
++ }
++
++ return delim_len;
++}
++
++/**
++ * fill_empty_space - Wipe the remaining Sidebar space
++ * @first_row: Screen line to start (0-based)
++ * @num_rows: Number of rows to fill
++ * @width: Width of the Sidebar (minus the divider)
++ *
++ * Write spaces over the area the sidebar isn't using.
++ */
++static void fill_empty_space (int first_row, int num_rows, int width)
++{
++ /* Fill the remaining rows with blank space */
++ SETCOLOR(MT_COLOR_NORMAL);
++
++ int r;
++ for (r = 0; r < num_rows; r++)
++ {
++ int i = 0;
++ move (first_row + r, 0);
++ for (; i < width; i++)
++ addch (' ');
++ }
++}
++
++/**
++ * draw_sidebar - Write out a list of mailboxes, on the left
++ * @first_row: Screen line to start (0-based)
++ * @num_rows: Number of rows to fill
++ * @div_width: Width in screen characters taken by the divider
++ *
++ * Display a list of mailboxes in a panel on the left. What's displayed will
++ * depend on our index markers: TopBuffy, OpnBuffy, HilBuffy, BotBuffy.
++ * On the first run they'll be NULL, so we display the top of Mutt's list
++ * (Incoming).
++ *
++ * TopBuffy - first visible mailbox
++ * BotBuffy - last visible mailbox
++ * OpnBuffy - mailbox shown in Mutt's Index Panel
++ * HilBuffy - Unselected mailbox (the paging follows this)
++ *
++ * The entries are formatted using "sidebar_format" and may be abbreviated:
++ * "sidebar_short_path", indented: "sidebar_folder_indent",
++ * "sidebar_indent_string" and sorted: "sidebar_sort_method". Finally, they're
++ * trimmed to fit the available space.
++ */
++static void draw_sidebar (int first_row, int num_rows, int div_width)
++{
++ BUFFY *b = TopBuffy;
++ if (!b)
++ return;
++
++ int w = MIN(COLS, (SidebarWidth - div_width));
++ int row = 0;
++ for (b = TopBuffy; b && (row < num_rows); b = b->next)
++ {
++ if (b->is_hidden)
++ continue;
++
++ if (b == OpnBuffy)
++ {
++ if ((ColorDefs[MT_COLOR_SB_INDICATOR] != 0))
++ SETCOLOR(MT_COLOR_SB_INDICATOR);
++ else
++ SETCOLOR(MT_COLOR_INDICATOR);
++ }
++ else if (b == HilBuffy)
++ SETCOLOR(MT_COLOR_HIGHLIGHT);
++ else if ((ColorDefs[MT_COLOR_SB_SPOOLFILE] != 0) &&
++ (mutt_strcmp (b->path, Spoolfile) == 0))
++ SETCOLOR(MT_COLOR_SB_SPOOLFILE);
++ else if (b->msg_unread > 0)
++ SETCOLOR(MT_COLOR_NEW);
++ else if (b->msg_flagged > 0)
++ SETCOLOR(MT_COLOR_FLAGGED);
++ else
++ SETCOLOR(MT_COLOR_NORMAL);
++
++ move (first_row + row, 0);
++ if (Context && Context->path &&
++ (!strcmp (b->path, Context->path)||
++ !strcmp (b->realpath, Context->path)))
++ {
++ b->msg_unread = Context->unread;
++ b->msg_count = Context->msgcount;
++ b->msg_flagged = Context->flagged;
+ }
+
-+ /* get attributes for divider */
-+ SETCOLOR(MT_COLOR_STATUS);
-+#ifndef USE_SLANG_CURSES
-+ attr_get(&attrs, &color_pair, 0);
-+#else
-+ color_pair = attr_get();
-+#endif
-+ SETCOLOR(MT_COLOR_NORMAL);
++ /* compute length of Maildir without trailing separator */
++ size_t maildirlen = strlen (Maildir);
++ if (SidebarDelimChars && strchr (SidebarDelimChars, Maildir[maildirlen - 1]))
++ maildirlen--;
+
-+ /* draw the divider */
++ /* check whether Maildir is a prefix of the current folder's path */
++ short maildir_is_prefix = 0;
++ if ((strlen (b->path) > maildirlen) && (strncmp (Maildir, b->path, maildirlen) == 0))
++ maildir_is_prefix = 1;
+
-+ for ( ; lines < LINES-1-(menu != MENU_PAGER || option(OPTSTATUSONTOP)); lines++ ) {
-+ move(lines, SidebarWidth - delim_len);
-+ addstr(NONULL(SidebarDelim));
-+#ifndef USE_SLANG_CURSES
-+ mvchgat(lines, SidebarWidth - delim_len, delim_len, 0, color_pair, NULL);
-+#endif
-+ }
-+
-+ if ( Incoming == 0 ) return 0;
-+ lines = option(OPTHELP) ? 1 : 0; /* go back to the top */
-+
-+ if ( known_lines != LINES || TopBuffy == 0 || BottomBuffy == 0 )
-+ calc_boundaries(menu);
-+ if ( CurBuffy == 0 ) CurBuffy = Incoming;
-+
-+ tmp = TopBuffy;
-+
-+ SETCOLOR(MT_COLOR_NORMAL);
-+
-+ for ( ; tmp && lines < LINES-1 - (menu != MENU_PAGER || option(OPTSTATUSONTOP)); tmp = tmp->next ) {
-+ if ( tmp == CurBuffy )
-+ SETCOLOR(MT_COLOR_INDICATOR);
-+ else if ( tmp->msg_unread > 0 )
-+ SETCOLOR(MT_COLOR_NEW);
-+ else if ( tmp->msg_flagged > 0 )
-+ SETCOLOR(MT_COLOR_FLAGGED);
-+ else
-+ SETCOLOR(MT_COLOR_NORMAL);
-+
-+ move( lines, 0 );
-+ if ( Context && !strcmp( tmp->path, Context->path ) ) {
-+ tmp->msg_unread = Context->unread;
-+ tmp->msgcount = Context->msgcount;
-+ tmp->msg_flagged = Context->flagged;
-+ }
-+ // check whether Maildir is a prefix of the current folder's path
-+ short maildir_is_prefix = 0;
-+ if ( (strlen(tmp->path) > strlen(Maildir)) &&
-+ (strncmp(Maildir, tmp->path, strlen(Maildir)) == 0) )
-+ maildir_is_prefix = 1;
-+ // calculate depth of current folder and generate its display name with indented spaces
-+ int sidebar_folder_depth = 0;
-+ char *sidebar_folder_name;
-+ sidebar_folder_name = basename(tmp->path);
-+ if ( maildir_is_prefix ) {
-+ char *tmp_folder_name;
-+ int i;
-+ tmp_folder_name = tmp->path + strlen(Maildir);
-+ for (i = 0; i < strlen(tmp->path) - strlen(Maildir); i++) {
-+ if (tmp_folder_name[i] == '/') sidebar_folder_depth++;
-+ }
-+ if (sidebar_folder_depth > 0) {
-+ sidebar_folder_name = malloc(strlen(basename(tmp->path)) + sidebar_folder_depth + 1);
-+ for (i=0; i < sidebar_folder_depth; i++)
-+ sidebar_folder_name[i]=' ';
-+ sidebar_folder_name[i]=0;
-+ strncat(sidebar_folder_name, basename(tmp->path), strlen(basename(tmp->path)) + sidebar_folder_depth);
-+ }
-+ }
-+ printw( "%.*s", SidebarWidth - delim_len + 1,
-+ make_sidebar_entry(sidebar_folder_name, tmp->msgcount,
-+ tmp->msg_unread, tmp->msg_flagged));
-+ if (sidebar_folder_depth > 0)
-+ free(sidebar_folder_name);
-+ lines++;
-+ }
-+ SETCOLOR(MT_COLOR_NORMAL);
-+ for ( ; lines < LINES-1 - (menu != MENU_PAGER || option(OPTSTATUSONTOP)); lines++ ) {
-+ int i = 0;
-+ move( lines, 0 );
-+ for ( ; i < SidebarWidth - delim_len; i++ )
-+ addch(' ');
-+ }
-+ return 0;
-+}
-+
-+
-+void set_buffystats(CONTEXT* Context)
-+{
-+ BUFFY *tmp = Incoming;
-+ while(tmp) {
-+ if(Context && !strcmp(tmp->path, Context->path)) {
-+ tmp->msg_unread = Context->unread;
-+ tmp->msgcount = Context->msgcount;
-+ break;
-+ }
-+ tmp = tmp->next;
++ /* calculate depth of current folder and generate its display name with indented spaces */
++ int sidebar_folder_depth = 0;
++ char *sidebar_folder_name;
++ int i;
++ if (option (OPTSIDEBARSHORTPATH))
++ {
++ /* disregard a trailing separator, so strlen() - 2 */
++ sidebar_folder_name = b->path;
++ for (i = strlen (sidebar_folder_name) - 2; i >= 0; i--)
++ {
++ if (SidebarDelimChars &&
++ strchr (SidebarDelimChars, sidebar_folder_name[i]))
++ {
++ sidebar_folder_name += (i + 1);
++ break;
+ }
++ }
++ }
++ else
++ sidebar_folder_name = b->path + maildir_is_prefix * (maildirlen + 1);
++
++ if (maildir_is_prefix && option (OPTSIDEBARFOLDERINDENT))
++ {
++ const char *tmp_folder_name;
++ int lastsep = 0;
++ tmp_folder_name = b->path + maildirlen + 1;
++ int tmplen = (int) strlen (tmp_folder_name) - 1;
++ for (i = 0; i < tmplen; i++)
++ {
++ if (SidebarDelimChars && strchr (SidebarDelimChars, tmp_folder_name[i]))
++ {
++ sidebar_folder_depth++;
++ lastsep = i + 1;
++ }
++ }
++ if (sidebar_folder_depth > 0)
++ {
++ if (option (OPTSIDEBARSHORTPATH))
++ tmp_folder_name += lastsep; /* basename */
++ sidebar_folder_name = malloc (strlen (tmp_folder_name) + sidebar_folder_depth*strlen (NONULL(SidebarIndentString)) + 1);
++ sidebar_folder_name[0]=0;
++ for (i=0; i < sidebar_folder_depth; i++)
++ strncat (sidebar_folder_name, NONULL(SidebarIndentString), strlen (NONULL(SidebarIndentString)));
++ strncat (sidebar_folder_name, tmp_folder_name, strlen (tmp_folder_name));
++ }
++ }
++ char str[STRING];
++ make_sidebar_entry (str, sizeof (str), w, sidebar_folder_name, b);
++ printw ("%s", str);
++ if (sidebar_folder_depth > 0)
++ FREE (&sidebar_folder_name);
++ row++;
++ }
++
++ fill_empty_space (first_row + row, num_rows - row, w);
+}
+
-+void scroll_sidebar(int op, int menu)
++
++/**
++ * mutt_sb_init - Set some default values for the sidebar.
++ */
++void
++mutt_sb_init (void)
+{
-+ if(!SidebarWidth) return;
-+ if(!CurBuffy) return;
-+
-+ switch (op) {
-+ case OP_SIDEBAR_NEXT:
-+ if ( CurBuffy->next == NULL ) return;
-+ CurBuffy = CurBuffy->next;
-+ break;
-+ case OP_SIDEBAR_PREV:
-+ if ( CurBuffy->prev == NULL ) return;
-+ CurBuffy = CurBuffy->prev;
-+ break;
-+ case OP_SIDEBAR_SCROLL_UP:
-+ CurBuffy = TopBuffy;
-+ if ( CurBuffy != Incoming ) {
-+ calc_boundaries(menu);
-+ CurBuffy = CurBuffy->prev;
-+ }
-+ break;
-+ case OP_SIDEBAR_SCROLL_DOWN:
-+ CurBuffy = BottomBuffy;
-+ if ( CurBuffy->next ) {
-+ calc_boundaries(menu);
-+ CurBuffy = CurBuffy->next;
-+ }
-+ break;
-+ default:
-+ return;
-+ }
-+ calc_boundaries(menu);
-+ draw_sidebar(menu);
++ OldVisible = option (OPTSIDEBAR);
++ if (SidebarWidth > 0)
++ {
++ OldWidth = SidebarWidth;
++ }
++ else
++ {
++ OldWidth = 20;
++ if (OldVisible)
++ {
++ SidebarWidth = OldWidth;
++ }
++ }
+}
+
-diff --git a/sidebar.h b/sidebar.h
-new file mode 100644
-index 0000000..d195f11
---- /dev/null
-+++ b/sidebar.h
++/**
++ * mutt_sb_draw - Completely redraw the sidebar
++ *
++ * Completely refresh the sidebar region. First draw the divider; then, for
++ * each BUFFY, call make_sidebar_entry; finally blank out any remaining space.
++ */
++void mutt_sb_draw (void)
++{
++ if (!visible())
++ return;
++
++ /* XXX - if transitioning from invisible to visible */
++ /* if (OldVisible == 0) */
++ /* mutt_buffy_check (1); we probably have bad or no numbers */
++
++ int x = getcurx (stdscr);
++ int y = getcury (stdscr);
++
++ int first_row = 0;
++ int num_rows = LINES - 2;
++
++ if (option (OPTHELP) || option (OPTSTATUSONTOP))
++ first_row++;
++
++ if (option (OPTHELP))
++ num_rows--;
++
++ int div_width = draw_divider (first_row, num_rows);
++ if (div_width < 0)
++ return;
++
++ if (!Incoming)
++ {
++ int w = MIN(COLS, (SidebarWidth - div_width));
++ fill_empty_space (first_row, num_rows, w);
++ return;
++ }
++
++ if (!prepare_sidebar (num_rows))
++ return;
++
++ draw_sidebar (first_row, num_rows, div_width);
++ move (y, x);
++}
++
++/**
++ * mutt_sb_should_refresh - Check if the sidebar is due to be refreshed
++ *
++ * The "sidebar_refresh_time" config option allows the user to limit the frequency
++ * with which the sidebar is refreshed.
++ *
++ * Returns:
++ * 1 Yes, refresh is due
++ * 0 No, refresh happened recently
++ */
++int mutt_sb_should_refresh (void)
++{
++ if (!option (OPTSIDEBAR))
++ return 0;
++
++ if (SidebarRefreshTime == 0)
++ return 0;
++
++ time_t diff = (time (NULL) - LastRefresh);
++
++ return (diff >= SidebarRefreshTime);
++}
++
++/**
++ * mutt_sb_change_mailbox - Change the selected mailbox
++ * @op: Operation code
++ *
++ * Change the selected mailbox, e.g. "Next mailbox", "Previous Mailbox
++ * with new mail". The operations are listed OPS.SIDEBAR which is built
++ * into an enum in keymap_defs.h.
++ *
++ * If the operation is successful, HilBuffy will be set to the new mailbox.
++ * This function only *selects* the mailbox, doesn't *open* it.
++ *
++ * Allowed values are: OP_SIDEBAR_NEXT, OP_SIDEBAR_NEXT_NEW,
++ * OP_SIDEBAR_PAGE_DOWN, OP_SIDEBAR_PAGE_UP, OP_SIDEBAR_PREV,
++ * OP_SIDEBAR_PREV_NEW.
++ */
++void mutt_sb_change_mailbox (int op)
++{
++ BUFFY *b;
++ if (!HilBuffy) /* It'll get reset on the next draw */
++ return;
++
++ switch (op)
++ {
++ case OP_SIDEBAR_NEXT:
++ if (!HilBuffy->next)
++ return;
++ if (HilBuffy->next->is_hidden)
++ return;
++ HilBuffy = HilBuffy->next;
++ break;
++ case OP_SIDEBAR_NEXT_NEW:
++ b = find_next_new (option (OPTSIDEBARNEXTNEWWRAP));
++ if (!b)
++ return;
++ else
++ HilBuffy = b;
++ break;
++ case OP_SIDEBAR_PAGE_DOWN:
++ HilBuffy = BotBuffy;
++ if (HilBuffy->next)
++ HilBuffy = HilBuffy->next;
++ break;
++ case OP_SIDEBAR_PAGE_UP:
++ HilBuffy = TopBuffy;
++ if (HilBuffy != Incoming)
++ HilBuffy = HilBuffy->prev;
++ break;
++ case OP_SIDEBAR_PREV:
++ if (!HilBuffy->prev)
++ return;
++ if (HilBuffy->prev->is_hidden) /* Can't happen, we've sorted the hidden to the end */
++ return;
++ HilBuffy = HilBuffy->prev;
++ break;
++ case OP_SIDEBAR_PREV_NEW:
++ b = find_prev_new (option (OPTSIDEBARNEXTNEWWRAP));
++ if (!b)
++ return;
++ else
++ HilBuffy = b;
++ break;
++ default:
++ return;
++ }
++
++ /* We can change folder even if the sidebar is hidden */
++ if (option (OPTSIDEBAR))
++ mutt_sb_draw();
++}
++
++/**
++ * mutt_sb_set_buffystats - Update the BUFFY's message counts from the CONTEXT
++ * @ctx: A mailbox CONTEXT
++ *
++ * Given a mailbox CONTEXT, find a matching mailbox BUFFY and copy the message
++ * counts into it.
++ */
++void mutt_sb_set_buffystats (const CONTEXT *ctx)
++{
++ /* Even if the sidebar's hidden,
++ * we should take note of the new data. */
++ BUFFY *b = Incoming;
++ if (!ctx || !b)
++ return;
++
++ for (; b; b = b->next)
++ {
++ if (!strcmp (b->path, ctx->path) ||
++ !strcmp (b->realpath, ctx->path))
++ {
++ b->msg_unread = ctx->unread;
++ b->msg_count = ctx->msgcount;
++ b->msg_flagged = ctx->flagged;
++ break;
++ }
++ }
++}
++
++/**
++ * mutt_sb_get_highlight - Get the BUFFY that's highlighted in the sidebar
++ *
++ * Get the path of the mailbox that's highlighted in the sidebar.
++ *
++ * Returns:
++ * Mailbox path
++ */
++const char *mutt_sb_get_highlight (void)
++{
++ if (!HilBuffy)
++ return NULL;
++
++ return HilBuffy->path;
++}
++
++/**
++ * mutt_sb_set_open_buffy - Set the OpnBuffy based on a mailbox path
++ * @path: Mailbox path
++ *
++ * Search through the list of mailboxes. If a BUFFY has a matching path, set
++ * OpnBuffy to it.
++ */
++BUFFY *mutt_sb_set_open_buffy (const char *path)
++{
++ /* Even if the sidebar is hidden */
++
++ BUFFY *b = Incoming;
++
++ if (!path || !b)
++ return NULL;
++
++ OpnBuffy = NULL;
++
++ for (; b; b = b->next)
++ {
++ if (!strcmp (b->path, path) ||
++ !strcmp (b->realpath, path))
++ {
++ OpnBuffy = b;
++ HilBuffy = b;
++ break;
++ }
++ }
++
++ return OpnBuffy;
++}
++
++/**
++ * mutt_sb_set_update_time - Note the time that the sidebar was updated
++ *
++ * Update the timestamp representing the last sidebar update. If the user
++ * configures "sidebar_refresh_time", this will help to reduce traffic.
++ */
++void mutt_sb_set_update_time (void)
++{
++ /* XXX - should this be public? */
++
++ LastRefresh = time (NULL);
++}
++
++/**
++ * mutt_sb_notify_mailbox - The state of a BUFFY is about to change
++ *
++ * We receive a notification:
++ * After a new BUFFY has been created
++ * Before a BUFFY is deleted
++ *
++ * Before a deletion, check that our pointers won't be invalidated.
++ */
++void mutt_sb_notify_mailbox (BUFFY *b, int created)
++{
++ if (!b)
++ return;
++
++ /* Any new/deleted mailboxes will cause a refresh. As long as
++ * they're valid, our pointers will be updated in prepare_sidebar() */
++
++ if (created)
++ {
++ if (!TopBuffy)
++ TopBuffy = b;
++ if (!HilBuffy)
++ HilBuffy = b;
++ if (!BotBuffy)
++ BotBuffy = b;
++ if (!Outgoing)
++ Outgoing = b;
++ if (!OpnBuffy && Context)
++ {
++ /* This might happen if the user "unmailboxes *", then
++ * "mailboxes" our current mailbox back again */
++ if (mutt_strcmp (b->path, Context->path) == 0)
++ OpnBuffy = b;
++ }
++ }
++ else
++ {
++ BUFFY *replacement = buffy_going (b);
++ if (TopBuffy == b)
++ TopBuffy = replacement;
++ if (OpnBuffy == b)
++ OpnBuffy = NULL;
++ if (HilBuffy == b)
++ HilBuffy = replacement;
++ if (BotBuffy == b)
++ BotBuffy = replacement;
++ if (Outgoing == b)
++ Outgoing = replacement;
++ }
++}
+diff -urN mutt-1.6.1/sidebar.h mutt-1.6.1-sidebar/sidebar.h
+--- mutt-1.6.1/sidebar.h 1970-01-01 01:00:00.000000000 +0100
++++ mutt-1.6.1-sidebar/sidebar.h 2016-06-12 18:43:03.967503185 +0100
@@ -0,0 +1,36 @@
-+/*
-+ * Copyright (C) ????-2004 Justin Hibbits
++/* Copyright (C) 2004 Justin Hibbits
+ * Copyright (C) 2004 Thomer M. Gil
-+ *
++ * Copyright (C) 2015-2016 Richard Russon
++ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
-+ *
++ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
-+ *
++ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
-+ */
++ */
+
+#ifndef SIDEBAR_H
+#define SIDEBAR_H
+
-+struct MBOX_LIST {
-+ char *path;
-+ int msgcount;
-+ int new;
-+} MBLIST;
++#include "mutt.h"
++#include "buffy.h"
+
-+/* parameter is whether or not to go to the status line */
-+/* used for omitting the last | that covers up the status bar in the index */
-+int draw_sidebar(int);
-+void scroll_sidebar(int, int);
-+void set_curbuffy(char*);
-+void set_buffystats(CONTEXT*);
++void mutt_sb_change_mailbox (int op);
++void mutt_sb_draw (void);
++const char * mutt_sb_get_highlight (void);
++void mutt_sb_init (void);
++void mutt_sb_notify_mailbox (BUFFY *b, int created);
++void mutt_sb_set_buffystats (const CONTEXT *ctx);
++BUFFY * mutt_sb_set_open_buffy (const char *path);
++void mutt_sb_set_update_time (void);
++int mutt_sb_should_refresh (void);
+
+#endif /* SIDEBAR_H */
+diff -urN mutt-1.6.1/sort.h mutt-1.6.1-sidebar/sort.h
+--- mutt-1.6.1/sort.h 2016-06-12 18:43:00.415447793 +0100
++++ mutt-1.6.1-sidebar/sort.h 2016-06-12 18:43:03.968503200 +0100
+@@ -31,6 +31,12 @@
+ #define SORT_KEYID 12
+ #define SORT_TRUST 13
+ #define SORT_SPAM 14
++#define SORT_COUNT 15
++#define SORT_COUNT_NEW 16
++#define SORT_DESC 17
++#define SORT_FLAGGED 18
++#define SORT_PATH 19
++
+ /* dgc: Sort & SortAux are shorts, so I'm bumping these bitflags up from
+ * bits 4 & 5 to bits 8 & 9 to make room for more sort keys in the future. */
+ #define SORT_MASK 0xff
+@@ -50,6 +56,7 @@
+ WHERE short Sort INITVAL (SORT_DATE);
+ WHERE short SortAux INITVAL (SORT_DATE); /* auxiliary sorting method */
+ WHERE short SortAlias INITVAL (SORT_ALIAS);
++WHERE short SidebarSortMethod INITVAL (SORT_ORDER);
+
+ /* FIXME: This one does not belong to here */
+ WHERE short PgpSortKeys INITVAL (SORT_ADDRESS);
diff --git a/pkgs/applications/networking/mailreaders/mutt/trash-folder.patch b/pkgs/applications/networking/mailreaders/mutt/trash-folder.patch
deleted file mode 100644
index ce47b0c30e5..00000000000
--- a/pkgs/applications/networking/mailreaders/mutt/trash-folder.patch
+++ /dev/null
@@ -1,316 +0,0 @@
-From: Cedric Duval
-Date: Thu, 27 Feb 2014 12:27:41 +0100
-Subject: trash-folder
-
-With this patch, if the trash variable is set to a path (unset by default), the
-deleted mails will be moved to a trash folder instead of being irremediably
-purged when syncing the mailbox.
-
-For instance, set trash="~/Mail/trash" will cause every deleted mail to go to
-this folder.
-
-Note that the append to the trash folder doesn't occur until the resync is
-done. This allows you to change your mind and undo deletes, and thus the moves
-to the trash folder are unnecessary.
-
-Notes
-
- * You might also want to have a look at the purge message feature below
- which is related to this patch.
- * IMAP is now supported. To retain the previous behavior, add this to your
- muttrc:
- folder-hook ^imap:// 'unset trash'
-
-FAQ
-
-Every once in a while, someone asks what are the advantages of this patch over
-a macro based solution. Here's an attempt to answer this question:
-
- * The folder history doesn't clutter up with unwanted trash entries.
- * Delayed move to the trash allows to change one's mind.
- * No need to treat the case of "normal folders" and trash folders
- separately with folder-hooks, and to create two sets of macros (one for
- the index, one for the pager).
- * Works not only with delete-message, but also with every deletion
- functions like delete-pattern, delete-thread or delete-subthread.
-
-To sum up, it's more integrated and transparent to the user.
-
-* Patch last synced with upstream:
- - Date: 2007-02-15
- - File: http://cedricduval.free.fr/mutt/patches/download/patch-1.5.5.1.cd.trash_folder.3.4
-
-* Changes made:
- - Updated to 1.5.13:
- - structure of _mutt_save_message changed (commands.c)
- - context of option (OPTCONFIRMAPPEND) changed (muttlib.c)
- - Fixed indentation of "appended" in mutt.h.
-
-Signed-off-by: Matteo F. Vescovi
-
-Gbp-Pq: Topic features
----
- commands.c | 1 +
- flags.c | 19 +++++++++++++++++-
- globals.h | 1 +
- imap/message.c | 2 ++
- init.h | 10 ++++++++++
- mutt.h | 3 +++
- muttlib.c | 4 +++-
- mx.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- postpone.c | 3 +++
- 9 files changed, 103 insertions(+), 2 deletions(-)
-
-diff --git a/commands.c b/commands.c
-index 5dbd100..7fd014b 100644
---- a/commands.c
-+++ b/commands.c
-@@ -720,6 +720,7 @@ int _mutt_save_message (HEADER *h, CONTEXT *ctx, int delete, int decode, int dec
- if (option (OPTDELETEUNTAG))
- mutt_set_flag (Context, h, M_TAG, 0);
- }
-+ mutt_set_flag (Context, h, M_APPENDED, 1);
-
- return 0;
- }
-diff --git a/flags.c b/flags.c
-index f0f3d81..dfa6a50 100644
---- a/flags.c
-+++ b/flags.c
-@@ -65,7 +65,13 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
- {
- h->deleted = 0;
- update = 1;
-- if (upd_ctx) ctx->deleted--;
-+ if (upd_ctx)
-+ {
-+ ctx->deleted--;
-+ if (h->appended)
-+ ctx->appended--;
-+ }
-+ h->appended = 0; /* when undeleting, also reset the appended flag */
- #ifdef USE_IMAP
- /* see my comment above */
- if (ctx->magic == M_IMAP)
-@@ -87,6 +93,17 @@ void _mutt_set_flag (CONTEXT *ctx, HEADER *h, int flag, int bf, int upd_ctx)
- }
- break;
-
-+ case M_APPENDED:
-+ if (bf)
-+ {
-+ if (!h->appended)
-+ {
-+ h->appended = 1;
-+ if (upd_ctx) ctx->appended++;
-+ }
-+ }
-+ break;
-+
- case M_NEW:
-
- if (!mutt_bit_isset(ctx->rights,M_ACL_SEEN))
-diff --git a/globals.h b/globals.h
-index e77030c..6a1b8da 100644
---- a/globals.h
-+++ b/globals.h
-@@ -144,6 +144,7 @@ WHERE char *Tochars;
- WHERE char *TSStatusFormat;
- WHERE char *TSIconFormat;
- WHERE short TSSupported;
-+WHERE char *TrashPath;
- WHERE char *Username;
- WHERE char *Visual;
-
-diff --git a/imap/message.c b/imap/message.c
-index 3877381..039fda6 100644
---- a/imap/message.c
-+++ b/imap/message.c
-@@ -884,6 +884,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
- if (ctx->hdrs[n]->tagged)
- {
- mutt_set_flag (ctx, ctx->hdrs[n], M_DELETE, 1);
-+ mutt_set_flag (ctx, ctx->hdrs[n], M_APPENDED, 1);
- if (option (OPTDELETEUNTAG))
- mutt_set_flag (ctx, ctx->hdrs[n], M_TAG, 0);
- }
-@@ -891,6 +892,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
- else
- {
- mutt_set_flag (ctx, h, M_DELETE, 1);
-+ mutt_set_flag (ctx, h, M_APPENDED, 1);
- if (option (OPTDELETEUNTAG))
- mutt_set_flag (ctx, h, M_TAG, 0);
- }
-diff --git a/init.h b/init.h
-index 6b49341..d3206f9 100644
---- a/init.h
-+++ b/init.h
-@@ -3341,6 +3341,16 @@ struct option_t MuttVars[] = {
- ** provided that ``$$ts_enabled'' has been set. This string is identical in
- ** formatting to the one used by ``$$status_format''.
- */
-+ { "trash", DT_PATH, R_NONE, UL &TrashPath, 0 },
-+ /*
-+ ** .pp
-+ ** If set, this variable specifies the path of the trash folder where the
-+ ** mails marked for deletion will be moved, instead of being irremediably
-+ ** purged.
-+ ** .pp
-+ ** NOTE: When you delete a message in the trash folder, it is really
-+ ** deleted, so that you have a way to clean the trash.
-+ */
- #ifdef USE_SOCKET
- { "tunnel", DT_STR, R_NONE, UL &Tunnel, UL 0 },
- /*
-diff --git a/mutt.h b/mutt.h
-index f8565fa..29bb6c2 100644
---- a/mutt.h
-+++ b/mutt.h
-@@ -185,6 +185,7 @@ enum
- M_DELETE,
- M_UNDELETE,
- M_DELETED,
-+ M_APPENDED,
- M_FLAG,
- M_TAG,
- M_UNTAG,
-@@ -713,6 +714,7 @@ typedef struct header
- unsigned int mime : 1; /* has a MIME-Version header? */
- unsigned int flagged : 1; /* marked important? */
- unsigned int tagged : 1;
-+ unsigned int appended : 1; /* has been saved */
- unsigned int deleted : 1;
- unsigned int changed : 1;
- unsigned int attach_del : 1; /* has an attachment marked for deletion */
-@@ -885,6 +887,7 @@ typedef struct _context
- int new; /* how many new messages? */
- int unread; /* how many unread messages? */
- int deleted; /* how many deleted messages */
-+ int appended; /* how many saved messages? */
- int flagged; /* how many flagged messages */
- int msgnotreadyet; /* which msg "new" in pager, -1 if none */
-
-diff --git a/muttlib.c b/muttlib.c
-index 02067cc..0fd9766 100644
---- a/muttlib.c
-+++ b/muttlib.c
-@@ -1505,7 +1505,9 @@ int mutt_save_confirm (const char *s, struct stat *st)
-
- if (magic > 0 && !mx_access (s, W_OK))
- {
-- if (option (OPTCONFIRMAPPEND))
-+ if (option (OPTCONFIRMAPPEND) &&
-+ (!TrashPath || (mutt_strcmp (s, TrashPath) != 0)))
-+ /* if we're appending to the trash, there's no point in asking */
- {
- snprintf (tmp, sizeof (tmp), _("Append messages to %s?"), s);
- if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO)
-diff --git a/mx.c b/mx.c
-index 4c5cb07..c0a6d30 100644
---- a/mx.c
-+++ b/mx.c
-@@ -776,6 +776,53 @@ static int sync_mailbox (CONTEXT *ctx, int *index_hint)
- return rc;
- }
-
-+/* move deleted mails to the trash folder */
-+static int trash_append (CONTEXT *ctx)
-+{
-+ CONTEXT *ctx_trash;
-+ int i = 0;
-+ struct stat st, stc;
-+
-+ if (!TrashPath || !ctx->deleted ||
-+ (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))
-+ return 0;
-+
-+ for (;i < ctx->msgcount && (!ctx->hdrs[i]->deleted ||
-+ ctx->hdrs[i]->appended); i++);
-+ if (i == ctx->msgcount)
-+ return 0; /* nothing to be done */
-+
-+ if (mutt_save_confirm (TrashPath, &st) != 0)
-+ {
-+ mutt_error _("message(s) not deleted");
-+ return -1;
-+ }
-+
-+ if (lstat (ctx->path, &stc) == 0 && stc.st_ino == st.st_ino
-+ && stc.st_dev == st.st_dev && stc.st_rdev == st.st_rdev)
-+ return 0; /* we are in the trash folder: simple sync */
-+
-+ if ((ctx_trash = mx_open_mailbox (TrashPath, M_APPEND, NULL)) != NULL)
-+ {
-+ for (i = 0 ; i < ctx->msgcount ; i++)
-+ if (ctx->hdrs[i]->deleted && !ctx->hdrs[i]->appended
-+ && mutt_append_message (ctx_trash, ctx, ctx->hdrs[i], 0, 0) == -1)
-+ {
-+ mx_close_mailbox (ctx_trash, NULL);
-+ return -1;
-+ }
-+
-+ mx_close_mailbox (ctx_trash, NULL);
-+ }
-+ else
-+ {
-+ mutt_error _("Can't open trash folder");
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
- /* save changes and close mailbox */
- int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
- {
-@@ -912,6 +959,7 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
- if (mutt_append_message (&f, ctx, ctx->hdrs[i], 0, CH_UPDATE_LEN) == 0)
- {
- mutt_set_flag (ctx, ctx->hdrs[i], M_DELETE, 1);
-+ mutt_set_flag (ctx, ctx->hdrs[i], M_APPENDED, 1);
- }
- else
- {
-@@ -936,6 +984,14 @@ int mx_close_mailbox (CONTEXT *ctx, int *index_hint)
- return 0;
- }
-
-+ /* copy mails to the trash before expunging */
-+ if (purge && ctx->deleted && mutt_strcmp(ctx->path, TrashPath))
-+ if (trash_append (ctx) != 0)
-+ {
-+ ctx->closing = 0;
-+ return -1;
-+ }
-+
- #ifdef USE_IMAP
- /* allow IMAP to preserve the deleted flag across sessions */
- if (ctx->magic == M_IMAP)
-@@ -1133,6 +1189,12 @@ int mx_sync_mailbox (CONTEXT *ctx, int *index_hint)
- msgcount = ctx->msgcount;
- deleted = ctx->deleted;
-
-+ if (purge && ctx->deleted && mutt_strcmp(ctx->path, TrashPath))
-+ {
-+ if (trash_append (ctx) == -1)
-+ return -1;
-+ }
-+
- #ifdef USE_IMAP
- if (ctx->magic == M_IMAP)
- rc = imap_sync_mailbox (ctx, purge, index_hint);
-diff --git a/postpone.c b/postpone.c
-index a703161..7a4cbb1 100644
---- a/postpone.c
-+++ b/postpone.c
-@@ -277,6 +277,9 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur, char *fcc, size
- /* finished with this message, so delete it. */
- mutt_set_flag (PostContext, h, M_DELETE, 1);
-
-+ /* and consider it saved, so that it won't be moved to the trash folder */
-+ mutt_set_flag (PostContext, h, M_APPENDED, 1);
-+
- /* update the count for the status display */
- PostCount = PostContext->msgcount - PostContext->deleted;
-
diff --git a/pkgs/applications/networking/mailreaders/mutt/trash.patch b/pkgs/applications/networking/mailreaders/mutt/trash.patch
new file mode 100644
index 00000000000..a7bda4c4c8b
--- /dev/null
+++ b/pkgs/applications/networking/mailreaders/mutt/trash.patch
@@ -0,0 +1,797 @@
+diff -urN mutt-1.6.1/commands.c mutt-1.6.1-trash/commands.c
+--- mutt-1.6.1/commands.c 2016-06-12 18:43:00.397447512 +0100
++++ mutt-1.6.1-trash/commands.c 2016-06-12 18:43:04.892517610 +0100
+@@ -720,6 +720,7 @@
+ if (option (OPTDELETEUNTAG))
+ mutt_set_flag (Context, h, M_TAG, 0);
+ }
++ mutt_set_flag (Context, h, M_APPENDED, 1);
+
+ return 0;
+ }
+diff -urN mutt-1.6.1/curs_main.c mutt-1.6.1-trash/curs_main.c
+--- mutt-1.6.1/curs_main.c 2016-06-12 18:43:00.399447544 +0100
++++ mutt-1.6.1-trash/curs_main.c 2016-06-12 18:43:04.895517656 +0100
+@@ -1919,6 +1919,7 @@
+ MAYBE_REDRAW (menu->redraw);
+ break;
+
++ case OP_PURGE_MESSAGE:
+ case OP_DELETE:
+
+ CHECK_MSGCOUNT;
+@@ -1930,6 +1931,7 @@
+ if (tag)
+ {
+ mutt_tag_set_flag (M_DELETE, 1);
++ mutt_tag_set_flag (M_PURGED, (op != OP_PURGE_MESSAGE) ? 0 : 1);
+ if (option (OPTDELETEUNTAG))
+ mutt_tag_set_flag (M_TAG, 0);
+ menu->redraw = REDRAW_INDEX;
+@@ -1937,6 +1939,8 @@
+ else
+ {
+ mutt_set_flag (Context, CURHDR, M_DELETE, 1);
++ mutt_set_flag (Context, CURHDR, M_PURGED,
++ (op != OP_PURGE_MESSAGE) ? 0 : 1);
+ if (option (OPTDELETEUNTAG))
+ mutt_set_flag (Context, CURHDR, M_TAG, 0);
+ if (option (OPTRESOLVE))
+@@ -2242,11 +2246,13 @@
+ if (tag)
+ {
+ mutt_tag_set_flag (M_DELETE, 0);
++ mutt_tag_set_flag (M_PURGED, 0);
+ menu->redraw = REDRAW_INDEX;
+ }
+ else
+ {
+ mutt_set_flag (Context, CURHDR, M_DELETE, 0);
++ mutt_set_flag (Context, CURHDR, M_PURGED, 0);
+ if (option (OPTRESOLVE) && menu->current < Context->vcount - 1)
+ {
+ menu->current++;
+@@ -2268,9 +2274,11 @@
+ CHECK_ACL(M_ACL_DELETE, _("Cannot undelete message(s)"));
+
+ rc = mutt_thread_set_flag (CURHDR, M_DELETE, 0,
+- op == OP_UNDELETE_THREAD ? 0 : 1);
++ op == OP_UNDELETE_THREAD ? 0 : 1)
++ + mutt_thread_set_flag (CURHDR, M_PURGED, 0,
++ (op == OP_UNDELETE_THREAD) ? 0 : 1);
+
+- if (rc != -1)
++ if (rc > -1)
+ {
+ if (option (OPTRESOLVE))
+ {
+diff -urN mutt-1.6.1/doc/manual.xml.head mutt-1.6.1-trash/doc/manual.xml.head
+--- mutt-1.6.1/doc/manual.xml.head 2016-06-12 18:43:00.402447590 +0100
++++ mutt-1.6.1-trash/doc/manual.xml.head 2016-06-12 18:43:04.901517750 +0100
+@@ -7467,6 +7467,16 @@
+
+
+
++
++Mutt Patches
++
++Mutt may also be patched to support smaller features.
++These patches should add a free-form string to the end Mutt's version string.
++Running mutt -v might show:
++patch-1.6.1.sidebar.20160502
++
++
++
+
+ URL Syntax
+
+@@ -8081,6 +8091,175 @@
+
+
+
++
++ Trash Folder Patch
++ Automatically move "deleted" emails to a trash bin
++
++
++ Patch
++
++
++ To check if Mutt supports Trash Folder, look for
++ patch-trash in the mutt version.
++ See: .
++
++
++ If IMAP is enabled, this patch will use it
++
++
++ Dependencies:
++ mutt-1.6.1
++ IMAP support
++
++
++ This patch is part of the NeoMutt Project.
++
++
++
++ Introduction
++
++
++ In Mutt, when you delete an email it is first marked
++ deleted. The email isn't really gone until
++ <sync-mailbox> is called.
++ This happens when the user leaves the folder, or the function is called
++ manually.
++
++
++
++ After <sync-mailbox> has been called the email is gone forever.
++
++
++
++ The $trash variable defines a folder in
++ which to keep old emails. As before, first you mark emails for
++ deletion. When <sync-mailbox> is called the emails are moved to
++ the trash folder.
++
++
++
++ The $trash path can be either a full directory,
++ or be relative to the $folder
++ variable, like the mailboxes command.
++
++
++
++ Emails deleted from the trash folder are gone forever.
++
++
++
++
++ Variables
++