View | Details | Raw Unified | Return to bug 94542
Collapse All | Expand All

(-)./Makefile (-11 / +6 lines)
Lines 101-107 Link Here
101
101
102
PORTNAME=	mutt-devel
102
PORTNAME=	mutt-devel
103
PORTVERSION=	1.5.11
103
PORTVERSION=	1.5.11
104
PORTREVISION?=	2
104
PORTREVISION?=	3
105
CATEGORIES+=	mail ipv6
105
CATEGORIES+=	mail ipv6
106
.if defined(WITH_MUTT_NNTP)
106
.if defined(WITH_MUTT_NNTP)
107
CATEGORIES+=	news
107
CATEGORIES+=	news
Lines 187-202 Link Here
187
.if defined(WITH_MUTT_MAILDIR_HEADER_CACHE)
187
.if defined(WITH_MUTT_MAILDIR_HEADER_CACHE)
188
WITH_MUTT_IMAP_HEADER_CACHE=	yes
188
WITH_MUTT_IMAP_HEADER_CACHE=	yes
189
.endif
189
.endif
190
.if defined(WITH_MUTT_SIGNATURE_MENU)
191
IGNORE=	cannot install: the WITH_MUTT_SIGNATURE_MENU does not work at the moment
192
.endif
193
.if defined(WITH_MUTT_SIDEBAR_PATCH)
190
.if defined(WITH_MUTT_SIDEBAR_PATCH)
194
.if defined(WITH_MUTT_NNTP)
191
.if defined(WITH_MUTT_NNTP)
195
IGNORE=	cannot install: the WITH_MUTT_SIDEBAR_PATCH and WITH_MUTT_NNTP are not compatible
192
IGNORE=	cannot install: the WITH_MUTT_SIDEBAR_PATCH and WITH_MUTT_NNTP are not compatible
196
.endif
193
.endif
197
.if defined(WITH_MUTT_SIGNATURE_MENU)
198
IGNORE=	cannot install: the WITH_MUTT_SIDEBAR_PATCH and WITH_MUTT_SIGNATURE_MENU are not compatible
199
.endif
200
.endif
194
.endif
201
.if defined(WITH_MUTT_ASSUMED_CHARSET_PATCH)
195
.if defined(WITH_MUTT_ASSUMED_CHARSET_PATCH)
202
.if defined(WITH_MUTT_NNTP)
196
.if defined(WITH_MUTT_NNTP)
Lines 311-316 Link Here
311
post-patch::
305
post-patch::
312
	@${PATCH} ${PATCH_ARGS} -p1 < ${PATCHDIR}/extra-patch-maildir-header-cache
306
	@${PATCH} ${PATCH_ARGS} -p1 < ${PATCHDIR}/extra-patch-maildir-header-cache
313
.endif
307
.endif
308
.if defined(WITH_MUTT_SIGNATURE_MENU)
309
XML_NEEDED=	yes
310
post-patch::
311
	@${PATCH} ${PATCH_ARGS} -p1 < ${PATCHDIR}/extra-patch-signature-menu
312
.endif
314
.if defined(WITH_MUTT_MAILDIR_MTIME_PATCH)
313
.if defined(WITH_MUTT_MAILDIR_MTIME_PATCH)
315
post-patch::
314
post-patch::
316
.if defined(WITH_MUTT_NNTP)
315
.if defined(WITH_MUTT_NNTP)
Lines 390-399 Link Here
390
.if ! defined(WITHOUT_MUTT_QUOTE_PATCH)
389
.if ! defined(WITHOUT_MUTT_QUOTE_PATCH)
391
PATCHFILES+=	patch-${VVV_PATCH_VERSION}.vvv.initials.gz:vvv \
390
PATCHFILES+=	patch-${VVV_PATCH_VERSION}.vvv.initials.gz:vvv \
392
		patch-${VVV_PATCH_VERSION}.vvv.quote.gz:vvv
391
		patch-${VVV_PATCH_VERSION}.vvv.quote.gz:vvv
393
XML_NEEDED=	yes
394
.endif
395
.if defined(WITH_MUTT_SIGNATURE_MENU)
396
PATCHFILES+=	patch-${CD_PATCH_VERSION}.cd.signatures_menu.2.1:cd
397
XML_NEEDED=	yes
392
XML_NEEDED=	yes
398
.endif
393
.endif
399
.if defined(WITH_MUTT_IFDEF_PATCH)
394
.if defined(WITH_MUTT_IFDEF_PATCH)
(-)./files/extra-patch-signature-menu (+729 lines)
Line 0 Link Here
1
--- mutt-1.5.11/PATCHES Dec 2002 17:44:54 -0000	3.6
2
+++ mutt-1.5.11/PATCHES Feb 2004 13:19:42 -0000
3
@@ -0,0 +1 @@
4
+patch-1.5.11.cd.signatures_menu.2.1
5
--- mutt-1.5.11/Makefile.am.orig	Thu Aug 11 23:27:28 2005
6
+++ mutt-1.5.11/Makefile.am	Sat Mar 11 21:47:55 2006
7
@@ -25,7 +25,7 @@
8
 	main.c mbox.c menu.c mh.c mx.c pager.c parse.c pattern.c \
9
 	postpone.c query.c recvattach.c recvcmd.c \
10
 	rfc822.c rfc1524.c rfc2047.c rfc2231.c \
11
-	score.c send.c sendlib.c signal.c sort.c \
12
+	score.c send.c sendlib.c signal.c signature.c sort.c \
13
 	status.c system.c thread.c charset.c history.c lib.c \
14
 	muttlib.c editmsg.c utf8.c mbyte.c wcwidth.c \
15
 	url.c ascii.c mutt_idna.c crypt-mod.c crypt-mod.h
16
--- mutt-1.5.11/Makefile.in.orig	Thu Sep 15 16:22:50 2005
17
+++ mutt-1.5.11/Makefile.in	Sat Mar 11 21:50:27 2006
18
@@ -89,7 +89,7 @@
19
 	recvattach.$(OBJEXT) recvcmd.$(OBJEXT) rfc822.$(OBJEXT) \
20
 	rfc1524.$(OBJEXT) rfc2047.$(OBJEXT) rfc2231.$(OBJEXT) \
21
 	score.$(OBJEXT) send.$(OBJEXT) sendlib.$(OBJEXT) \
22
-	signal.$(OBJEXT) sort.$(OBJEXT) status.$(OBJEXT) \
23
+	signal.$(OBJEXT) signature.${OBJEXT} sort.$(OBJEXT) status.$(OBJEXT) \
24
 	system.$(OBJEXT) thread.$(OBJEXT) charset.$(OBJEXT) \
25
 	history.$(OBJEXT) lib.$(OBJEXT) muttlib.$(OBJEXT) \
26
 	editmsg.$(OBJEXT) utf8.$(OBJEXT) mbyte.$(OBJEXT) \
27
@@ -307,7 +307,7 @@
28
 	main.c mbox.c menu.c mh.c mx.c pager.c parse.c pattern.c \
29
 	postpone.c query.c recvattach.c recvcmd.c \
30
 	rfc822.c rfc1524.c rfc2047.c rfc2231.c \
31
-	score.c send.c sendlib.c signal.c sort.c \
32
+	score.c send.c sendlib.c signal.c signature.c sort.c \
33
 	status.c system.c thread.c charset.c history.c lib.c \
34
 	muttlib.c editmsg.c utf8.c mbyte.c wcwidth.c \
35
 	url.c ascii.c mutt_idna.c crypt-mod.c crypt-mod.h
36
--- mutt-1.5.11/OPS.orig	Sun Jul 24 18:56:42 2005
37
+++ mutt-1.5.11/OPS	Sat Mar 11 21:47:55 2006
38
@@ -38,6 +38,7 @@
39
 OP_COMPOSE_POSTPONE_MESSAGE "save this message to send later"
40
 OP_COMPOSE_RENAME_FILE "rename/move an attached file"
41
 OP_COMPOSE_SEND_MESSAGE "send the message"
42
+OP_COMPOSE_SIG "choose a signature"
43
 OP_COMPOSE_TOGGLE_DISPOSITION "toggle disposition between inline/attachment"
44
 OP_COMPOSE_TOGGLE_UNLINK "toggle whether to delete file after sending it"
45
 OP_COMPOSE_UPDATE_ENCODING "update an attachment's encoding info"
46
@@ -131,6 +132,7 @@
47
 OP_NEXT_ENTRY "move to the next entry"
48
 OP_NEXT_LINE "scroll down one line"
49
 OP_NEXT_PAGE "move to the next page"
50
+OP_NEXT_SIG "move to the next signature"
51
 OP_PAGER_BOTTOM "jump to the bottom of the message"
52
 OP_PAGER_HIDE_QUOTED "toggle display of quoted text"
53
 OP_PAGER_SKIP_QUOTED "skip beyond quoted text"
54
@@ -139,10 +141,12 @@
55
 OP_PREV_ENTRY "move to the previous entry"
56
 OP_PREV_LINE "scroll up one line"
57
 OP_PREV_PAGE "move to the previous page"
58
+OP_PREV_SIG "move to the previous signature"
59
 OP_PRINT "print the current entry"
60
 OP_QUERY "query external program for addresses"
61
 OP_QUERY_APPEND "append new query results to current results"
62
 OP_QUIT "save changes to mailbox and quit"
63
+OP_RANDOM_SIG "pick a signature at random"
64
 OP_RECALL_MESSAGE "recall a postponed message"
65
 OP_REDRAW "clear and redraw the screen"
66
 OP_REFORMAT_WINCH "{internal}"
67
@@ -156,6 +160,7 @@
68
 OP_SEARCH_OPPOSITE "search for next match in opposite direction"
69
 OP_SEARCH_TOGGLE "toggle search pattern coloring"
70
 OP_SHELL_ESCAPE "invoke a command in a subshell"
71
+OP_SIG_SEARCH "search signatures matching a pattern"
72
 OP_SORT "sort messages"
73
 OP_SORT_REVERSE "sort messages in reverse order"
74
 OP_TAG "tag the current entry"
75
--- mutt-1.5.11/compose.c.orig	Thu Aug 11 21:37:23 2005
76
+++ mutt-1.5.11/compose.c	Sat Mar 11 21:47:55 2006
77
@@ -1128,6 +1128,12 @@
78
         /* no send2hook, since this doesn't modify the message */
79
 	break;
80
 
81
+      case OP_COMPOSE_SIG:
82
+	mutt_signature(msg->content->filename);
83
+	MAYBE_REDRAW (menu->redraw);
84
+	mutt_update_encoding (msg->content);
85
+	break;
86
+
87
       case OP_PIPE:
88
       case OP_FILTER:
89
         CHECK_COUNT;
90
--- mutt-1.5.11/doc/manual.xml.head.orig	Tue Sep  6 18:46:44 2005
91
+++ mutt-1.5.11/doc/manual.xml.head	Sat Mar 11 21:48:05 2006
92
@@ -908,6 +908,7 @@
93
 c       edit-cc                 edit the Cc field
94
 b       edit-bcc                edit the Bcc field
95
 y       send-message            send the message
96
+ESC s	signature-menu		select a signature and append it to your mail
97
 s       edit-subject            edit the Subject
98
 S       smime-menu              select S/MIME options
99
 f       edit-fcc                specify an ``Fcc'' mailbox
100
--- mutt-1.5.11/functions.h.orig	Sun Jul 24 18:56:42 2005
101
+++ mutt-1.5.11/functions.h	Sat Mar 11 21:48:05 2006
102
@@ -311,6 +311,7 @@
103
   { "view-attach",	OP_VIEW_ATTACH,			M_ENTER_S },
104
   { "send-message",	OP_COMPOSE_SEND_MESSAGE,	"y" },
105
   { "pipe-entry",	OP_PIPE,			"|" },
106
+  { "signature-menu",	OP_COMPOSE_SIG,			"\033s" },
107
 
108
   { "attach-key",	OP_COMPOSE_ATTACH_KEY,		"\033k" },
109
   { "pgp-menu",		OP_COMPOSE_PGP_MENU,		"p" 	},
110
@@ -368,6 +369,19 @@
111
   { "mail",		OP_MAIL,		"m" },
112
   { "query",		OP_QUERY,		"Q" },
113
   { "query-append",	OP_QUERY_APPEND,	"A" },
114
+  { NULL,		0,			NULL }
115
+};
116
+
117
+/* Signature Menu */
118
+struct binding_t OpSig[] = {
119
+  { "next-sig",		OP_NEXT_SIG,		"j" },
120
+  { "previous-sig",	OP_PREV_SIG,		"k" },
121
+  { "random-sig",	OP_RANDOM_SIG,		"r" },
122
+  { NULL,		0,			NULL }
123
+};
124
+
125
+struct binding_t OpSigDir[] = {
126
+  { "search-sig",	OP_SIG_SEARCH,		"/" },
127
   { NULL,		0,			NULL }
128
 };
129
 
130
--- mutt-1.5.11/globals.h.orig	Thu Sep 15 16:19:54 2005
131
+++ mutt-1.5.11/globals.h	Sat Mar 11 21:48:05 2006
132
@@ -109,6 +109,7 @@
133
 WHERE char *Sendmail;
134
 WHERE char *Shell;
135
 WHERE char *Signature;
136
+WHERE char *SigDirectory;
137
 WHERE char *SimpleSearch;
138
 WHERE char *Spoolfile;
139
 WHERE char *SpamSep;
140
--- mutt-1.5.11/init.h.orig	Thu Sep 15 16:19:54 2005
141
+++ mutt-1.5.11/init.h	Sat Mar 11 21:48:05 2006
142
@@ -2457,6 +2457,14 @@
143
   ** assumed that filename is a shell command and input should be read from
144
   ** its stdout.
145
   */
146
+  { "signatures_directory",	DT_PATH, R_NONE, UL &SigDirectory, UL "" },
147
+  /*
148
+  ** .pp
149
+  ** Specifies the path where your signatures are located. In the files of
150
+  ** this directory, the signatures are separated by blank lines and/or
151
+  ** sig_dashes (``-- '').
152
+  ** You can choose between these signatures from the compose menu.
153
+  */
154
   { "simple_search",	DT_STR,	 R_NONE, UL &SimpleSearch, UL "~f %s | ~s %s" },
155
   /*
156
   ** .pp
157
--- mutt-1.5.11/keymap.c.orig	Wed Sep  7 10:19:43 2005
158
+++ mutt-1.5.11/keymap.c	Sat Mar 11 21:48:05 2006
159
@@ -55,6 +55,8 @@
160
   
161
 
162
  { "query",	MENU_QUERY },
163
+ { "signature",	MENU_SIG },
164
+ { "sig_directory",	MENU_SIG_DIR },
165
  { "generic",	MENU_GENERIC },
166
  { NULL,	0 }
167
 };
168
@@ -560,6 +562,8 @@
169
   create_bindings (OpPost, MENU_POST);
170
   create_bindings (OpQuery, MENU_QUERY);
171
   create_bindings (OpAlias, MENU_ALIAS);
172
+  create_bindings (OpSig, MENU_SIG);
173
+  create_bindings (OpSigDir, MENU_SIG_DIR);
174
 
175
 
176
   if ((WithCrypto & APPLICATION_PGP))
177
@@ -658,6 +662,9 @@
178
   km_bindkey ("<enter>", MENU_ATTACH, OP_VIEW_ATTACH);
179
   km_bindkey ("<enter>", MENU_COMPOSE, OP_VIEW_ATTACH);
180
 
181
+  km_bindkey ("<up>", MENU_SIG, OP_PREV_SIG);
182
+  km_bindkey ("<down>", MENU_SIG, OP_NEXT_SIG);
183
+
184
   /* edit-to (default "t") hides generic tag-entry in Compose menu
185
      This will bind tag-entry to  "T" in the Compose menu */
186
   km_bindkey ("T", MENU_COMPOSE, OP_TAG);
187
@@ -793,6 +800,10 @@
188
       return OpEditor;
189
     case MENU_QUERY:
190
       return OpQuery;
191
+    case MENU_SIG:
192
+      return OpSig;
193
+    case MENU_SIG_DIR:
194
+      return OpSigDir;
195
 
196
     case MENU_PGP:
197
       return (WithCrypto & APPLICATION_PGP)? OpPgp:NULL;
198
--- mutt-1.5.11/keymap.h.orig	Thu Jun 17 22:33:04 2004
199
+++ mutt-1.5.11/keymap.h	Sat Mar 11 21:48:05 2006
200
@@ -62,6 +62,8 @@
201
   MENU_PAGER,
202
   MENU_POST,
203
   MENU_QUERY,
204
+  MENU_SIG,
205
+  MENU_SIG_DIR,
206
 
207
   
208
   MENU_PGP,
209
@@ -108,6 +110,8 @@
210
 extern struct binding_t OpEditor[];
211
 extern struct binding_t OpQuery[];
212
 extern struct binding_t OpAlias[];
213
+extern struct binding_t OpSig[];
214
+extern struct binding_t OpSigDir[];
215
 
216
 extern struct binding_t OpPgp[];
217
 
218
--- mutt-1.5.11/protos.h.orig	Wed Sep  7 10:19:43 2005
219
+++ mutt-1.5.11/protos.h	Sat Mar 11 21:48:05 2006
220
@@ -242,6 +242,7 @@
221
 void mutt_shell_escape (void);
222
 void mutt_show_error (void);
223
 void mutt_signal_init (void);
224
+void mutt_signature (char *);
225
 void mutt_stamp_attachment (BODY *a);
226
 void mutt_tabs_to_spaces (char *);
227
 void mutt_tag_set_flag (int, int);
228
--- mutt-1.5.11/signature.c.orig	Sat Mar 11 21:58:38 2006
229
+++ mutt-1.5.11/signature.c	Sat Mar 11 22:07:31 2006
230
@@ -0,0 +1,499 @@
231
+/*
232
+ * Copyright (C) 2001 Cedric Duval <cedricduval@free.fr>
233
+ * 
234
+ *     This program is free software; you can redistribute it and/or modify
235
+ *     it under the terms of the GNU General Public License as published by
236
+ *     the Free Software Foundation; either version 2 of the License, or
237
+ *     (at your option) any later version.
238
+ * 
239
+ *     This program is distributed in the hope that it will be useful,
240
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
241
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
242
+ *     GNU General Public License for more details.
243
+ * 
244
+ *     You should have received a copy of the GNU General Public License
245
+ *     along with this program; if not, write to the Free Software
246
+ *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
247
+ */
248
+
249
+#if HAVE_CONFIG_H
250
+# include "config.h"
251
+#endif
252
+
253
+#include "mutt.h"
254
+#include "mutt_menu.h"
255
+#include "mapping.h"
256
+#include "mutt_curses.h"
257
+
258
+#include <stdio.h>
259
+#include <string.h>
260
+#include <stdlib.h>
261
+#include <dirent.h>
262
+#include <sys/stat.h>
263
+
264
+#define SIG_DISPLAY_LINES 4
265
+#define SEPARATOR(x) ((*x == '\n') || (mutt_strcmp (x, "-- \n") == 0))
266
+#define SIG_ADD_LINE(x,y) mutt_add_list (x, strtok (y, "\n"))
267
+
268
+typedef struct sig_list
269
+{
270
+  struct sig_list *next;
271
+  LIST *sig;
272
+} SIG_LIST;
273
+
274
+typedef struct sig_dir
275
+{
276
+  struct sig_dir *next;
277
+  char *name;
278
+} SIG_DIR;
279
+
280
+typedef LIST * ENTRY;
281
+
282
+typedef struct entry_dir
283
+{
284
+  int tagged;
285
+  SIG_DIR *data;
286
+} ENTRY_DIR;
287
+
288
+static struct mapping_t SigHelp[] = {
289
+  { N_("Exit"),   OP_EXIT },
290
+  { N_("Search"), OP_SEARCH },
291
+  { N_("Random"), OP_RANDOM_SIG },
292
+  { N_("Help"),   OP_HELP },
293
+  { NULL }
294
+};
295
+
296
+static struct mapping_t SigDirHelp[] = {
297
+  { N_("Exit"),   OP_EXIT },
298
+  { N_("Search signature"), OP_SIG_SEARCH },
299
+  { N_("Help"),   OP_HELP },
300
+  { NULL }
301
+};
302
+
303
+void menu_next_entry (MUTTMENU *menu);
304
+void menu_prev_entry (MUTTMENU *menu);
305
+
306
+
307
+static int sig_match (LIST *s, regex_t *re)
308
+{
309
+  while (s)
310
+  {
311
+    if (regexec (re, s->data, (size_t)0, NULL, (int)0) == 0)
312
+      return 1;
313
+    s = s->next;
314
+  }
315
+  return 0;
316
+}
317
+
318
+static void read_sig_file (char *name, SIG_LIST **begin, regex_t *re)
319
+{
320
+  FILE *fp;
321
+  char buf[STRING];
322
+  LIST *sig = NULL;
323
+  SIG_LIST *first, *cur;
324
+  int append = 0;
325
+
326
+  if (!(fp = safe_fopen (name, "r")))
327
+  {
328
+    mutt_error (_("Can't open signature file %s"), name);
329
+    return;
330
+  }
331
+
332
+  for (first = *begin; first && first->next; first = first->next, append++)
333
+    ; /* append results to an existing list */
334
+  cur = first;
335
+
336
+  while (fgets (buf, sizeof (buf), fp))
337
+  {
338
+    if (buf[0] && !SEPARATOR (buf))
339
+    {
340
+      sig = SIG_ADD_LINE (NULL, buf);
341
+
342
+      while (fgets (buf, sizeof (buf), fp) && buf[0] && !SEPARATOR (buf))
343
+	SIG_ADD_LINE (sig, buf);
344
+
345
+      if (re && !sig_match (sig, re))
346
+	mutt_free_list (&sig); /* previous sig didn't match the regexp */
347
+      else
348
+      {
349
+	/* add signature */
350
+	if (first == NULL)
351
+	  first = cur = (SIG_LIST *) safe_calloc (1, sizeof (SIG_LIST));
352
+	else
353
+	{
354
+	  cur->next = (SIG_LIST *) safe_calloc (1, sizeof (SIG_LIST));
355
+	  cur = cur->next;
356
+	}
357
+
358
+	cur->sig = sig;
359
+	cur->next = NULL;
360
+      }
361
+    }
362
+  }
363
+
364
+  if (!append)
365
+    *begin = first;
366
+
367
+  safe_fclose (&fp);
368
+}
369
+
370
+static void sig_make_entry (char *s, size_t slen, MUTTMENU *menu, int num)
371
+{
372
+  ENTRY *table = (ENTRY *) menu->data;
373
+
374
+  snprintf (s, slen, "%3d %s",
375
+	    num + 1,
376
+	    table[num]->data);
377
+}
378
+
379
+static int sig_menu_search (MUTTMENU *menu, regex_t *re, int num)
380
+{
381
+  return (sig_match (((ENTRY *)menu->data)[num], re) ? 0 : REG_NOMATCH);
382
+}
383
+
384
+static void draw_sig_frame (LIST *s)
385
+{
386
+  int i;
387
+
388
+  for (i = 1; i <= SIG_DISPLAY_LINES; i++)
389
+  {
390
+    if (s)
391
+    {
392
+      mvaddstr (i, 0, s->data);
393
+      s = s->next;
394
+    }
395
+    else
396
+      move (i, 0);
397
+
398
+    clrtoeol ();
399
+  }
400
+
401
+  SETCOLOR (MT_COLOR_STATUS);
402
+  mvaddstr (SIG_DISPLAY_LINES + 1, 0, _("-- Signature"));
403
+  BKGDSET (MT_COLOR_STATUS);
404
+  clrtoeol ();
405
+
406
+  BKGDSET (MT_COLOR_NORMAL);
407
+  SETCOLOR (MT_COLOR_NORMAL);
408
+}
409
+
410
+static void free_sig_list (SIG_LIST **sigs)
411
+{
412
+  SIG_LIST *cur;
413
+
414
+  while (*sigs)
415
+  {
416
+    cur = *sigs;
417
+    *sigs = (*sigs)->next;
418
+    mutt_free_list (&cur->sig);
419
+    safe_free ((void **)&cur);
420
+  }
421
+}
422
+
423
+static void append_signature (char *msg_file, LIST *s)
424
+{
425
+  FILE *fp;
426
+
427
+  if ((fp = safe_fopen (msg_file, "a")) == 0)
428
+    mutt_perror (msg_file);
429
+  else
430
+  {
431
+    if (option (OPTSIGDASHES))
432
+      fputs ("\n-- \n", fp);
433
+
434
+    for (; s; s = s->next)
435
+      fprintf (fp, "%s\n", s->data);
436
+
437
+    mutt_message (_("Signature appended to your mail"));
438
+    safe_fclose (&fp);
439
+  }
440
+}
441
+
442
+static LIST *sig_list_menu (char *file, SIG_LIST *list)
443
+{
444
+  LIST *result = NULL;
445
+  SIG_LIST *sigl;
446
+  MUTTMENU *menu;
447
+  ENTRY *SigTable;
448
+  char helpstr[SHORT_STRING], title[SHORT_STRING];
449
+  int i, done = 0;
450
+
451
+  snprintf (title, sizeof (title), _("Signature : %s"), file);
452
+
453
+  menu = mutt_new_menu ();
454
+  menu->make_entry = sig_make_entry;
455
+  menu->tag = NULL;
456
+  menu->search = sig_menu_search;
457
+  menu->menu = MENU_SIG;
458
+  menu->title = title;
459
+  menu->help = mutt_compile_help (helpstr, sizeof (helpstr),
460
+				  MENU_SIG, SigHelp);
461
+  menu->offset = SIG_DISPLAY_LINES + 2;
462
+  menu->pagelen = LINES - SIG_DISPLAY_LINES - 4;
463
+  
464
+  for (sigl = list; sigl; sigl = sigl->next)
465
+    menu->max++;
466
+
467
+  menu->data = SigTable = (ENTRY *) safe_calloc (menu->max, sizeof (ENTRY));
468
+
469
+  for (i = 0, sigl = list; sigl; i++, sigl = sigl->next)
470
+    SigTable[i] = sigl->sig;
471
+
472
+  while (!done)
473
+  {
474
+    switch (mutt_menuLoop (menu))
475
+    {
476
+      case OP_GENERIC_SELECT_ENTRY:
477
+        result = SigTable[menu->current];
478
+	done = 1;
479
+	break;
480
+
481
+      case OP_PREV_SIG:
482
+	menu_prev_entry (menu);
483
+	draw_sig_frame (SigTable[menu->current]);
484
+	break;
485
+
486
+      case OP_NEXT_SIG:
487
+	menu_next_entry (menu);
488
+	draw_sig_frame (SigTable[menu->current]);
489
+	break;
490
+
491
+      case OP_REDRAW:
492
+	menu->offset = SIG_DISPLAY_LINES + 2;
493
+	menu->pagelen = LINES - SIG_DISPLAY_LINES - 4;
494
+	draw_sig_frame (SigTable[menu->current]);
495
+	break;
496
+
497
+      case OP_RANDOM_SIG:
498
+	menu->current = LRAND () % menu->max;
499
+	draw_sig_frame (SigTable[menu->current]);
500
+	menu->redraw |= REDRAW_MOTION;
501
+	break;
502
+
503
+      case OP_EXIT:
504
+	set_option (OPTNEEDREDRAW);
505
+        done = 1;
506
+        break;
507
+    }
508
+  }
509
+  
510
+  mutt_menuDestroy (&menu);
511
+  safe_free ((void **)&SigTable);
512
+  return result;
513
+}
514
+
515
+static SIG_LIST *sig_search_filter (MUTTMENU *menu, char *path)
516
+{
517
+  regex_t re;
518
+  char buf[STRING];
519
+  SIG_LIST *result = NULL;
520
+  int i;
521
+
522
+  snprintf (buf, sizeof(buf), menu->searchBuf ? menu->searchBuf : "");
523
+  if (mutt_get_field (_("Search for: "), buf,
524
+		      sizeof (buf), M_CLEAR) != 0 || !buf[0])
525
+    return (NULL);
526
+  mutt_str_replace (&menu->searchBuf, buf);
527
+
528
+  if ((i = regcomp (&re, menu->searchBuf, REG_NOSUB | REG_EXTENDED | REG_WORDS
529
+		    | mutt_which_case (menu->searchBuf))) != 0)
530
+  {
531
+    regerror (i, &re, buf, sizeof (buf));
532
+    regfree (&re);
533
+    mutt_error ("%s", buf);
534
+    return (NULL);
535
+  }
536
+
537
+  /* building list of sigs matching the regexp */
538
+  for (i = 0; i < menu->max; i++)
539
+  {
540
+    /* search in every file if none is tagged */
541
+    if (((ENTRY_DIR *) menu->data)[i].tagged || (menu->tagged == 0))
542
+    {
543
+      snprintf (buf, sizeof (buf), "%s/%s", path,
544
+		((ENTRY_DIR *) menu->data)[i].data->name);
545
+      read_sig_file (buf, &result, &re);
546
+    }
547
+  }
548
+
549
+  regfree (&re);
550
+  if (!result)
551
+    mutt_error (_("Not found."));
552
+
553
+  return (result);
554
+}
555
+
556
+/* returns the list of files in this directory */
557
+static SIG_DIR *sig_directory (char *path)
558
+{
559
+  DIR *dp;
560
+  struct dirent *de;
561
+  struct stat s;
562
+  SIG_DIR *first = NULL, *cur = NULL;
563
+  char file[_POSIX_PATH_MAX + SHORT_STRING];
564
+
565
+  if ((dp = opendir (path)) == NULL)
566
+  {
567
+    mutt_perror (path);
568
+    return (NULL);
569
+  }
570
+  
571
+  while ((de = readdir (dp)))
572
+  {
573
+    if ((de->d_name)[0] == '.') /* no hidden files */
574
+      continue;
575
+
576
+    snprintf (file, sizeof (file), "%s/%s", path, de->d_name);
577
+    if (lstat (file, &s) == -1)
578
+      continue;
579
+
580
+    if ((!S_ISREG (s.st_mode)) && (!S_ISLNK (s.st_mode)))
581
+      continue;
582
+
583
+    if (first == NULL)
584
+      cur = first = safe_calloc (1, sizeof (SIG_DIR));
585
+    else
586
+    {
587
+      cur->next = safe_calloc (1, sizeof (SIG_DIR));
588
+      cur = cur->next;
589
+    }
590
+    cur->name = safe_strdup (de->d_name);
591
+    cur->next = NULL;
592
+  }
593
+  closedir (dp);
594
+  return first;
595
+}
596
+
597
+static void sig_dir_make_entry (char *s, size_t slen, MUTTMENU *menu, int num)
598
+{
599
+  ENTRY_DIR *table = (ENTRY_DIR *) menu->data;
600
+
601
+  snprintf (s, slen, "%c %3d - %s",
602
+	    table[num].tagged ? '*' : ' ',
603
+	    num + 1,
604
+	    table[num].data->name);
605
+}
606
+
607
+static int sig_dir_tag (MUTTMENU *menu, int n, int m)
608
+{
609
+  ENTRY_DIR *cur = &((ENTRY_DIR *) menu->data)[n];
610
+  int ot = cur->tagged;
611
+  
612
+  cur->tagged = m >= 0 ? m : !cur->tagged;
613
+  return cur->tagged - ot;
614
+
615
+}
616
+
617
+static int sig_dir_sort (const void *a, const void *b)
618
+{
619
+  ENTRY_DIR *pa = (ENTRY_DIR *) a;
620
+  ENTRY_DIR *pb = (ENTRY_DIR *) b;
621
+
622
+  return (mutt_strcmp (pa->data->name, pb->data->name));
623
+}
624
+
625
+static int sig_dir_menu (char *path, char *msg_file)
626
+{
627
+  MUTTMENU *menu;
628
+  SIG_LIST *sigl;
629
+  LIST *result = NULL;
630
+  ENTRY_DIR *FileTable;
631
+  SIG_DIR *list, *files;
632
+  char buf[STRING], helpstr[SHORT_STRING], title[SHORT_STRING];
633
+  int i, done = 0;
634
+
635
+  if ((list = sig_directory (path)) == NULL)
636
+    return -1;
637
+
638
+  snprintf (title, sizeof (title), "Signature directory : %s", path);
639
+
640
+  menu = mutt_new_menu ();
641
+  menu->make_entry = sig_dir_make_entry;
642
+  menu->search = NULL; /* search within files with sig_search_filter() */
643
+  menu->tag = sig_dir_tag;
644
+  menu->menu = MENU_SIG_DIR;
645
+  menu->title = title;
646
+  menu->help = mutt_compile_help (helpstr, sizeof (helpstr),
647
+				  MENU_SIG_DIR, SigDirHelp);
648
+
649
+  for (files = list; files; files = files->next)
650
+    menu->max++;
651
+
652
+  menu->data = FileTable = (ENTRY_DIR *) safe_calloc (menu->max,
653
+						      sizeof (ENTRY_DIR));
654
+
655
+  for (i = 0, files = list; files; i++, files = files->next)
656
+    FileTable[i].data = files;
657
+
658
+  qsort (FileTable, menu->max, sizeof (ENTRY_DIR), sig_dir_sort);
659
+
660
+  while (!done)
661
+  {
662
+    switch (mutt_menuLoop (menu))
663
+    {
664
+      case OP_SIG_SEARCH:
665
+	sigl = sig_search_filter (menu, path);
666
+
667
+	if (sigl)
668
+	{
669
+	  if ((result = sig_list_menu (_("query results"), sigl)) != NULL)
670
+	  {
671
+	    append_signature (msg_file, result);
672
+	    done = 1;
673
+	  }
674
+
675
+	  MAYBE_REDRAW (menu->redraw);
676
+	  free_sig_list (&sigl);
677
+	}
678
+	break;
679
+
680
+      case OP_GENERIC_SELECT_ENTRY:
681
+	snprintf (buf, sizeof (buf), "%s/%s", path,
682
+		  FileTable[menu->current].data->name);
683
+	sigl = NULL;
684
+	read_sig_file (buf, &sigl, NULL);
685
+
686
+	if (sigl)
687
+	{
688
+	  if ((result = sig_list_menu (buf, sigl)) != NULL)
689
+	  {
690
+	    append_signature (msg_file, result);
691
+	    done = 1;
692
+	  }
693
+
694
+	  MAYBE_REDRAW (menu->redraw);
695
+	  free_sig_list (&sigl);
696
+      	}
697
+	break;
698
+
699
+      case OP_EXIT:
700
+        done = 1;
701
+        break;
702
+    }
703
+  }
704
+
705
+  while (list)
706
+  {
707
+    safe_free ((void **)&list->name);
708
+    files = list;
709
+    list = list->next;
710
+    safe_free ((void **)&files);
711
+  }
712
+  safe_free ((void **)&FileTable);
713
+  mutt_menuDestroy (&menu);
714
+  return 0;
715
+}
716
+
717
+void mutt_signature (char *msg_file)
718
+{
719
+  if (!SigDirectory)
720
+  {
721
+    mutt_error (_("variable 'signatures_directory' is unset"));
722
+    return;
723
+  }
724
+
725
+  if (sig_dir_menu (SigDirectory, msg_file) == -1)
726
+    mutt_error (_("%s: no files in this directory"), SigDirectory);
727
+  else
728
+    set_option (OPTNEEDREDRAW);
729
+}
(-)./patch-1.5.11.cd.signatures_menu.2.1 (+726 lines)
Line 0 Link Here
1
--- mutt-1.5.11/Makefile.am.orig	Thu Aug 11 23:27:28 2005
2
+++ mutt-1.5.11/Makefile.am	Sat Mar 11 21:47:55 2006
3
@@ -25,7 +25,7 @@
4
 	main.c mbox.c menu.c mh.c mx.c pager.c parse.c pattern.c \
5
 	postpone.c query.c recvattach.c recvcmd.c \
6
 	rfc822.c rfc1524.c rfc2047.c rfc2231.c \
7
-	score.c send.c sendlib.c signal.c sort.c \
8
+	score.c send.c sendlib.c signal.c signature.c sort.c \
9
 	status.c system.c thread.c charset.c history.c lib.c \
10
 	muttlib.c editmsg.c utf8.c mbyte.c wcwidth.c \
11
 	url.c ascii.c mutt_idna.c crypt-mod.c crypt-mod.h
12
--- mutt-1.5.11/Makefile.in.orig	Thu Sep 15 16:22:50 2005
13
+++ mutt-1.5.11/Makefile.in	Sat Mar 11 21:50:27 2006
14
@@ -89,7 +89,7 @@
15
 	recvattach.$(OBJEXT) recvcmd.$(OBJEXT) rfc822.$(OBJEXT) \
16
 	rfc1524.$(OBJEXT) rfc2047.$(OBJEXT) rfc2231.$(OBJEXT) \
17
 	score.$(OBJEXT) send.$(OBJEXT) sendlib.$(OBJEXT) \
18
-	signal.$(OBJEXT) sort.$(OBJEXT) status.$(OBJEXT) \
19
+	signal.$(OBJEXT) signature.${OBJEXT} sort.$(OBJEXT) status.$(OBJEXT) \
20
 	system.$(OBJEXT) thread.$(OBJEXT) charset.$(OBJEXT) \
21
 	history.$(OBJEXT) lib.$(OBJEXT) muttlib.$(OBJEXT) \
22
 	editmsg.$(OBJEXT) utf8.$(OBJEXT) mbyte.$(OBJEXT) \
23
@@ -307,7 +307,7 @@
24
 	main.c mbox.c menu.c mh.c mx.c pager.c parse.c pattern.c \
25
 	postpone.c query.c recvattach.c recvcmd.c \
26
 	rfc822.c rfc1524.c rfc2047.c rfc2231.c \
27
-	score.c send.c sendlib.c signal.c sort.c \
28
+	score.c send.c sendlib.c signal.c signature.c sort.c \
29
 	status.c system.c thread.c charset.c history.c lib.c \
30
 	muttlib.c editmsg.c utf8.c mbyte.c wcwidth.c \
31
 	url.c ascii.c mutt_idna.c crypt-mod.c crypt-mod.h
32
--- mutt-1.5.11/OPS.orig	Sun Jul 24 18:56:42 2005
33
+++ mutt-1.5.11/OPS	Sat Mar 11 21:47:55 2006
34
@@ -38,6 +38,7 @@
35
 OP_COMPOSE_POSTPONE_MESSAGE "save this message to send later"
36
 OP_COMPOSE_RENAME_FILE "rename/move an attached file"
37
 OP_COMPOSE_SEND_MESSAGE "send the message"
38
+OP_COMPOSE_SIG "choose a signature"
39
 OP_COMPOSE_TOGGLE_DISPOSITION "toggle disposition between inline/attachment"
40
 OP_COMPOSE_TOGGLE_UNLINK "toggle whether to delete file after sending it"
41
 OP_COMPOSE_UPDATE_ENCODING "update an attachment's encoding info"
42
@@ -131,6 +132,7 @@
43
 OP_NEXT_ENTRY "move to the next entry"
44
 OP_NEXT_LINE "scroll down one line"
45
 OP_NEXT_PAGE "move to the next page"
46
+OP_NEXT_SIG "move to the next signature"
47
 OP_PAGER_BOTTOM "jump to the bottom of the message"
48
 OP_PAGER_HIDE_QUOTED "toggle display of quoted text"
49
 OP_PAGER_SKIP_QUOTED "skip beyond quoted text"
50
@@ -139,10 +141,12 @@
51
 OP_PREV_ENTRY "move to the previous entry"
52
 OP_PREV_LINE "scroll up one line"
53
 OP_PREV_PAGE "move to the previous page"
54
+OP_PREV_SIG "move to the previous signature"
55
 OP_PRINT "print the current entry"
56
 OP_QUERY "query external program for addresses"
57
 OP_QUERY_APPEND "append new query results to current results"
58
 OP_QUIT "save changes to mailbox and quit"
59
+OP_RANDOM_SIG "pick a signature at random"
60
 OP_RECALL_MESSAGE "recall a postponed message"
61
 OP_REDRAW "clear and redraw the screen"
62
 OP_REFORMAT_WINCH "{internal}"
63
@@ -156,6 +160,7 @@
64
 OP_SEARCH_OPPOSITE "search for next match in opposite direction"
65
 OP_SEARCH_TOGGLE "toggle search pattern coloring"
66
 OP_SHELL_ESCAPE "invoke a command in a subshell"
67
+OP_SIG_SEARCH "search signatures matching a pattern"
68
 OP_SORT "sort messages"
69
 OP_SORT_REVERSE "sort messages in reverse order"
70
 OP_TAG "tag the current entry"
71
Binary files mutt-1.5.11/PATCHES.orig and mutt-1.5.11/PATCHES differ
72
--- mutt-1.5.11/compose.c.orig	Thu Aug 11 21:37:23 2005
73
+++ mutt-1.5.11/compose.c	Sat Mar 11 21:47:55 2006
74
@@ -1128,6 +1128,12 @@
75
         /* no send2hook, since this doesn't modify the message */
76
 	break;
77
 
78
+      case OP_COMPOSE_SIG:
79
+	mutt_signature(msg->content->filename);
80
+	MAYBE_REDRAW (menu->redraw);
81
+	mutt_update_encoding (msg->content);
82
+	break;
83
+
84
       case OP_PIPE:
85
       case OP_FILTER:
86
         CHECK_COUNT;
87
--- mutt-1.5.11/doc/manual.xml.head.orig	Tue Sep  6 18:46:44 2005
88
+++ mutt-1.5.11/doc/manual.xml.head	Sat Mar 11 21:48:05 2006
89
@@ -908,6 +908,7 @@
90
 c       edit-cc                 edit the Cc field
91
 b       edit-bcc                edit the Bcc field
92
 y       send-message            send the message
93
+ESC s	signature-menu		select a signature and append it to your mail
94
 s       edit-subject            edit the Subject
95
 S       smime-menu              select S/MIME options
96
 f       edit-fcc                specify an ``Fcc'' mailbox
97
--- mutt-1.5.11/functions.h.orig	Sun Jul 24 18:56:42 2005
98
+++ mutt-1.5.11/functions.h	Sat Mar 11 21:48:05 2006
99
@@ -311,6 +311,7 @@
100
   { "view-attach",	OP_VIEW_ATTACH,			M_ENTER_S },
101
   { "send-message",	OP_COMPOSE_SEND_MESSAGE,	"y" },
102
   { "pipe-entry",	OP_PIPE,			"|" },
103
+  { "signature-menu",	OP_COMPOSE_SIG,			"\033s" },
104
 
105
   { "attach-key",	OP_COMPOSE_ATTACH_KEY,		"\033k" },
106
   { "pgp-menu",		OP_COMPOSE_PGP_MENU,		"p" 	},
107
@@ -368,6 +369,19 @@
108
   { "mail",		OP_MAIL,		"m" },
109
   { "query",		OP_QUERY,		"Q" },
110
   { "query-append",	OP_QUERY_APPEND,	"A" },
111
+  { NULL,		0,			NULL }
112
+};
113
+
114
+/* Signature Menu */
115
+struct binding_t OpSig[] = {
116
+  { "next-sig",		OP_NEXT_SIG,		"j" },
117
+  { "previous-sig",	OP_PREV_SIG,		"k" },
118
+  { "random-sig",	OP_RANDOM_SIG,		"r" },
119
+  { NULL,		0,			NULL }
120
+};
121
+
122
+struct binding_t OpSigDir[] = {
123
+  { "search-sig",	OP_SIG_SEARCH,		"/" },
124
   { NULL,		0,			NULL }
125
 };
126
 
127
--- mutt-1.5.11/globals.h.orig	Thu Sep 15 16:19:54 2005
128
+++ mutt-1.5.11/globals.h	Sat Mar 11 21:48:05 2006
129
@@ -109,6 +109,7 @@
130
 WHERE char *Sendmail;
131
 WHERE char *Shell;
132
 WHERE char *Signature;
133
+WHERE char *SigDirectory;
134
 WHERE char *SimpleSearch;
135
 WHERE char *Spoolfile;
136
 WHERE char *SpamSep;
137
--- mutt-1.5.11/init.h.orig	Thu Sep 15 16:19:54 2005
138
+++ mutt-1.5.11/init.h	Sat Mar 11 21:48:05 2006
139
@@ -2457,6 +2457,14 @@
140
   ** assumed that filename is a shell command and input should be read from
141
   ** its stdout.
142
   */
143
+  { "signatures_directory",	DT_PATH, R_NONE, UL &SigDirectory, UL "" },
144
+  /*
145
+  ** .pp
146
+  ** Specifies the path where your signatures are located. In the files of
147
+  ** this directory, the signatures are separated by blank lines and/or
148
+  ** sig_dashes (``-- '').
149
+  ** You can choose between these signatures from the compose menu.
150
+  */
151
   { "simple_search",	DT_STR,	 R_NONE, UL &SimpleSearch, UL "~f %s | ~s %s" },
152
   /*
153
   ** .pp
154
--- mutt-1.5.11/keymap.c.orig	Wed Sep  7 10:19:43 2005
155
+++ mutt-1.5.11/keymap.c	Sat Mar 11 21:48:05 2006
156
@@ -55,6 +55,8 @@
157
   
158
 
159
  { "query",	MENU_QUERY },
160
+ { "signature",	MENU_SIG },
161
+ { "sig_directory",	MENU_SIG_DIR },
162
  { "generic",	MENU_GENERIC },
163
  { NULL,	0 }
164
 };
165
@@ -560,6 +562,8 @@
166
   create_bindings (OpPost, MENU_POST);
167
   create_bindings (OpQuery, MENU_QUERY);
168
   create_bindings (OpAlias, MENU_ALIAS);
169
+  create_bindings (OpSig, MENU_SIG);
170
+  create_bindings (OpSigDir, MENU_SIG_DIR);
171
 
172
 
173
   if ((WithCrypto & APPLICATION_PGP))
174
@@ -658,6 +662,9 @@
175
   km_bindkey ("<enter>", MENU_ATTACH, OP_VIEW_ATTACH);
176
   km_bindkey ("<enter>", MENU_COMPOSE, OP_VIEW_ATTACH);
177
 
178
+  km_bindkey ("<up>", MENU_SIG, OP_PREV_SIG);
179
+  km_bindkey ("<down>", MENU_SIG, OP_NEXT_SIG);
180
+
181
   /* edit-to (default "t") hides generic tag-entry in Compose menu
182
      This will bind tag-entry to  "T" in the Compose menu */
183
   km_bindkey ("T", MENU_COMPOSE, OP_TAG);
184
@@ -793,6 +800,10 @@
185
       return OpEditor;
186
     case MENU_QUERY:
187
       return OpQuery;
188
+    case MENU_SIG:
189
+      return OpSig;
190
+    case MENU_SIG_DIR:
191
+      return OpSigDir;
192
 
193
     case MENU_PGP:
194
       return (WithCrypto & APPLICATION_PGP)? OpPgp:NULL;
195
--- mutt-1.5.11/keymap.h.orig	Thu Jun 17 22:33:04 2004
196
+++ mutt-1.5.11/keymap.h	Sat Mar 11 21:48:05 2006
197
@@ -62,6 +62,8 @@
198
   MENU_PAGER,
199
   MENU_POST,
200
   MENU_QUERY,
201
+  MENU_SIG,
202
+  MENU_SIG_DIR,
203
 
204
   
205
   MENU_PGP,
206
@@ -108,6 +110,8 @@
207
 extern struct binding_t OpEditor[];
208
 extern struct binding_t OpQuery[];
209
 extern struct binding_t OpAlias[];
210
+extern struct binding_t OpSig[];
211
+extern struct binding_t OpSigDir[];
212
 
213
 extern struct binding_t OpPgp[];
214
 
215
--- mutt-1.5.11/protos.h.orig	Wed Sep  7 10:19:43 2005
216
+++ mutt-1.5.11/protos.h	Sat Mar 11 21:48:05 2006
217
@@ -242,6 +242,7 @@
218
 void mutt_shell_escape (void);
219
 void mutt_show_error (void);
220
 void mutt_signal_init (void);
221
+void mutt_signature (char *);
222
 void mutt_stamp_attachment (BODY *a);
223
 void mutt_tabs_to_spaces (char *);
224
 void mutt_tag_set_flag (int, int);
225
--- mutt-1.5.11/signature.c.orig	Sat Mar 11 21:58:38 2006
226
+++ mutt-1.5.11/signature.c	Sat Mar 11 22:07:31 2006
227
@@ -0,0 +1,499 @@
228
+/*
229
+ * Copyright (C) 2001 Cedric Duval <cedricduval@free.fr>
230
+ * 
231
+ *     This program is free software; you can redistribute it and/or modify
232
+ *     it under the terms of the GNU General Public License as published by
233
+ *     the Free Software Foundation; either version 2 of the License, or
234
+ *     (at your option) any later version.
235
+ * 
236
+ *     This program is distributed in the hope that it will be useful,
237
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
238
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
239
+ *     GNU General Public License for more details.
240
+ * 
241
+ *     You should have received a copy of the GNU General Public License
242
+ *     along with this program; if not, write to the Free Software
243
+ *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
244
+ */
245
+
246
+#if HAVE_CONFIG_H
247
+# include "config.h"
248
+#endif
249
+
250
+#include "mutt.h"
251
+#include "mutt_menu.h"
252
+#include "mapping.h"
253
+#include "mutt_curses.h"
254
+
255
+#include <stdio.h>
256
+#include <string.h>
257
+#include <stdlib.h>
258
+#include <dirent.h>
259
+#include <sys/stat.h>
260
+
261
+#define SIG_DISPLAY_LINES 4
262
+#define SEPARATOR(x) ((*x == '\n') || (mutt_strcmp (x, "-- \n") == 0))
263
+#define SIG_ADD_LINE(x,y) mutt_add_list (x, strtok (y, "\n"))
264
+
265
+typedef struct sig_list
266
+{
267
+  struct sig_list *next;
268
+  LIST *sig;
269
+} SIG_LIST;
270
+
271
+typedef struct sig_dir
272
+{
273
+  struct sig_dir *next;
274
+  char *name;
275
+} SIG_DIR;
276
+
277
+typedef LIST * ENTRY;
278
+
279
+typedef struct entry_dir
280
+{
281
+  int tagged;
282
+  SIG_DIR *data;
283
+} ENTRY_DIR;
284
+
285
+static struct mapping_t SigHelp[] = {
286
+  { N_("Exit"),   OP_EXIT },
287
+  { N_("Search"), OP_SEARCH },
288
+  { N_("Random"), OP_RANDOM_SIG },
289
+  { N_("Help"),   OP_HELP },
290
+  { NULL }
291
+};
292
+
293
+static struct mapping_t SigDirHelp[] = {
294
+  { N_("Exit"),   OP_EXIT },
295
+  { N_("Search signature"), OP_SIG_SEARCH },
296
+  { N_("Help"),   OP_HELP },
297
+  { NULL }
298
+};
299
+
300
+void menu_next_entry (MUTTMENU *menu);
301
+void menu_prev_entry (MUTTMENU *menu);
302
+
303
+
304
+static int sig_match (LIST *s, regex_t *re)
305
+{
306
+  while (s)
307
+  {
308
+    if (regexec (re, s->data, (size_t)0, NULL, (int)0) == 0)
309
+      return 1;
310
+    s = s->next;
311
+  }
312
+  return 0;
313
+}
314
+
315
+static void read_sig_file (char *name, SIG_LIST **begin, regex_t *re)
316
+{
317
+  FILE *fp;
318
+  char buf[STRING];
319
+  LIST *sig = NULL;
320
+  SIG_LIST *first, *cur;
321
+  int append = 0;
322
+
323
+  if (!(fp = safe_fopen (name, "r")))
324
+  {
325
+    mutt_error (_("Can't open signature file %s"), name);
326
+    return;
327
+  }
328
+
329
+  for (first = *begin; first && first->next; first = first->next, append++)
330
+    ; /* append results to an existing list */
331
+  cur = first;
332
+
333
+  while (fgets (buf, sizeof (buf), fp))
334
+  {
335
+    if (buf[0] && !SEPARATOR (buf))
336
+    {
337
+      sig = SIG_ADD_LINE (NULL, buf);
338
+
339
+      while (fgets (buf, sizeof (buf), fp) && buf[0] && !SEPARATOR (buf))
340
+	SIG_ADD_LINE (sig, buf);
341
+
342
+      if (re && !sig_match (sig, re))
343
+	mutt_free_list (&sig); /* previous sig didn't match the regexp */
344
+      else
345
+      {
346
+	/* add signature */
347
+	if (first == NULL)
348
+	  first = cur = (SIG_LIST *) safe_calloc (1, sizeof (SIG_LIST));
349
+	else
350
+	{
351
+	  cur->next = (SIG_LIST *) safe_calloc (1, sizeof (SIG_LIST));
352
+	  cur = cur->next;
353
+	}
354
+
355
+	cur->sig = sig;
356
+	cur->next = NULL;
357
+      }
358
+    }
359
+  }
360
+
361
+  if (!append)
362
+    *begin = first;
363
+
364
+  safe_fclose (&fp);
365
+}
366
+
367
+static void sig_make_entry (char *s, size_t slen, MUTTMENU *menu, int num)
368
+{
369
+  ENTRY *table = (ENTRY *) menu->data;
370
+
371
+  snprintf (s, slen, "%3d %s",
372
+	    num + 1,
373
+	    table[num]->data);
374
+}
375
+
376
+static int sig_menu_search (MUTTMENU *menu, regex_t *re, int num)
377
+{
378
+  return (sig_match (((ENTRY *)menu->data)[num], re) ? 0 : REG_NOMATCH);
379
+}
380
+
381
+static void draw_sig_frame (LIST *s)
382
+{
383
+  int i;
384
+
385
+  for (i = 1; i <= SIG_DISPLAY_LINES; i++)
386
+  {
387
+    if (s)
388
+    {
389
+      mvaddstr (i, 0, s->data);
390
+      s = s->next;
391
+    }
392
+    else
393
+      move (i, 0);
394
+
395
+    clrtoeol ();
396
+  }
397
+
398
+  SETCOLOR (MT_COLOR_STATUS);
399
+  mvaddstr (SIG_DISPLAY_LINES + 1, 0, _("-- Signature"));
400
+  BKGDSET (MT_COLOR_STATUS);
401
+  clrtoeol ();
402
+
403
+  BKGDSET (MT_COLOR_NORMAL);
404
+  SETCOLOR (MT_COLOR_NORMAL);
405
+}
406
+
407
+static void free_sig_list (SIG_LIST **sigs)
408
+{
409
+  SIG_LIST *cur;
410
+
411
+  while (*sigs)
412
+  {
413
+    cur = *sigs;
414
+    *sigs = (*sigs)->next;
415
+    mutt_free_list (&cur->sig);
416
+    safe_free ((void **)&cur);
417
+  }
418
+}
419
+
420
+static void append_signature (char *msg_file, LIST *s)
421
+{
422
+  FILE *fp;
423
+
424
+  if ((fp = safe_fopen (msg_file, "a")) == 0)
425
+    mutt_perror (msg_file);
426
+  else
427
+  {
428
+    if (option (OPTSIGDASHES))
429
+      fputs ("\n-- \n", fp);
430
+
431
+    for (; s; s = s->next)
432
+      fprintf (fp, "%s\n", s->data);
433
+
434
+    mutt_message (_("Signature appended to your mail"));
435
+    safe_fclose (&fp);
436
+  }
437
+}
438
+
439
+static LIST *sig_list_menu (char *file, SIG_LIST *list)
440
+{
441
+  LIST *result = NULL;
442
+  SIG_LIST *sigl;
443
+  MUTTMENU *menu;
444
+  ENTRY *SigTable;
445
+  char helpstr[SHORT_STRING], title[SHORT_STRING];
446
+  int i, done = 0;
447
+
448
+  snprintf (title, sizeof (title), _("Signature : %s"), file);
449
+
450
+  menu = mutt_new_menu ();
451
+  menu->make_entry = sig_make_entry;
452
+  menu->tag = NULL;
453
+  menu->search = sig_menu_search;
454
+  menu->menu = MENU_SIG;
455
+  menu->title = title;
456
+  menu->help = mutt_compile_help (helpstr, sizeof (helpstr),
457
+				  MENU_SIG, SigHelp);
458
+  menu->offset = SIG_DISPLAY_LINES + 2;
459
+  menu->pagelen = LINES - SIG_DISPLAY_LINES - 4;
460
+  
461
+  for (sigl = list; sigl; sigl = sigl->next)
462
+    menu->max++;
463
+
464
+  menu->data = SigTable = (ENTRY *) safe_calloc (menu->max, sizeof (ENTRY));
465
+
466
+  for (i = 0, sigl = list; sigl; i++, sigl = sigl->next)
467
+    SigTable[i] = sigl->sig;
468
+
469
+  while (!done)
470
+  {
471
+    switch (mutt_menuLoop (menu))
472
+    {
473
+      case OP_GENERIC_SELECT_ENTRY:
474
+        result = SigTable[menu->current];
475
+	done = 1;
476
+	break;
477
+
478
+      case OP_PREV_SIG:
479
+	menu_prev_entry (menu);
480
+	draw_sig_frame (SigTable[menu->current]);
481
+	break;
482
+
483
+      case OP_NEXT_SIG:
484
+	menu_next_entry (menu);
485
+	draw_sig_frame (SigTable[menu->current]);
486
+	break;
487
+
488
+      case OP_REDRAW:
489
+	menu->offset = SIG_DISPLAY_LINES + 2;
490
+	menu->pagelen = LINES - SIG_DISPLAY_LINES - 4;
491
+	draw_sig_frame (SigTable[menu->current]);
492
+	break;
493
+
494
+      case OP_RANDOM_SIG:
495
+	menu->current = LRAND () % menu->max;
496
+	draw_sig_frame (SigTable[menu->current]);
497
+	menu->redraw |= REDRAW_MOTION;
498
+	break;
499
+
500
+      case OP_EXIT:
501
+	set_option (OPTNEEDREDRAW);
502
+        done = 1;
503
+        break;
504
+    }
505
+  }
506
+  
507
+  mutt_menuDestroy (&menu);
508
+  safe_free ((void **)&SigTable);
509
+  return result;
510
+}
511
+
512
+static SIG_LIST *sig_search_filter (MUTTMENU *menu, char *path)
513
+{
514
+  regex_t re;
515
+  char buf[STRING];
516
+  SIG_LIST *result = NULL;
517
+  int i;
518
+
519
+  snprintf (buf, sizeof(buf), menu->searchBuf ? menu->searchBuf : "");
520
+  if (mutt_get_field (_("Search for: "), buf,
521
+		      sizeof (buf), M_CLEAR) != 0 || !buf[0])
522
+    return (NULL);
523
+  mutt_str_replace (&menu->searchBuf, buf);
524
+
525
+  if ((i = regcomp (&re, menu->searchBuf, REG_NOSUB | REG_EXTENDED | REG_WORDS
526
+		    | mutt_which_case (menu->searchBuf))) != 0)
527
+  {
528
+    regerror (i, &re, buf, sizeof (buf));
529
+    regfree (&re);
530
+    mutt_error ("%s", buf);
531
+    return (NULL);
532
+  }
533
+
534
+  /* building list of sigs matching the regexp */
535
+  for (i = 0; i < menu->max; i++)
536
+  {
537
+    /* search in every file if none is tagged */
538
+    if (((ENTRY_DIR *) menu->data)[i].tagged || (menu->tagged == 0))
539
+    {
540
+      snprintf (buf, sizeof (buf), "%s/%s", path,
541
+		((ENTRY_DIR *) menu->data)[i].data->name);
542
+      read_sig_file (buf, &result, &re);
543
+    }
544
+  }
545
+
546
+  regfree (&re);
547
+  if (!result)
548
+    mutt_error (_("Not found."));
549
+
550
+  return (result);
551
+}
552
+
553
+/* returns the list of files in this directory */
554
+static SIG_DIR *sig_directory (char *path)
555
+{
556
+  DIR *dp;
557
+  struct dirent *de;
558
+  struct stat s;
559
+  SIG_DIR *first = NULL, *cur = NULL;
560
+  char file[_POSIX_PATH_MAX + SHORT_STRING];
561
+
562
+  if ((dp = opendir (path)) == NULL)
563
+  {
564
+    mutt_perror (path);
565
+    return (NULL);
566
+  }
567
+  
568
+  while ((de = readdir (dp)))
569
+  {
570
+    if ((de->d_name)[0] == '.') /* no hidden files */
571
+      continue;
572
+
573
+    snprintf (file, sizeof (file), "%s/%s", path, de->d_name);
574
+    if (lstat (file, &s) == -1)
575
+      continue;
576
+
577
+    if ((!S_ISREG (s.st_mode)) && (!S_ISLNK (s.st_mode)))
578
+      continue;
579
+
580
+    if (first == NULL)
581
+      cur = first = safe_calloc (1, sizeof (SIG_DIR));
582
+    else
583
+    {
584
+      cur->next = safe_calloc (1, sizeof (SIG_DIR));
585
+      cur = cur->next;
586
+    }
587
+    cur->name = safe_strdup (de->d_name);
588
+    cur->next = NULL;
589
+  }
590
+  closedir (dp);
591
+  return first;
592
+}
593
+
594
+static void sig_dir_make_entry (char *s, size_t slen, MUTTMENU *menu, int num)
595
+{
596
+  ENTRY_DIR *table = (ENTRY_DIR *) menu->data;
597
+
598
+  snprintf (s, slen, "%c %3d - %s",
599
+	    table[num].tagged ? '*' : ' ',
600
+	    num + 1,
601
+	    table[num].data->name);
602
+}
603
+
604
+static int sig_dir_tag (MUTTMENU *menu, int n, int m)
605
+{
606
+  ENTRY_DIR *cur = &((ENTRY_DIR *) menu->data)[n];
607
+  int ot = cur->tagged;
608
+  
609
+  cur->tagged = m >= 0 ? m : !cur->tagged;
610
+  return cur->tagged - ot;
611
+
612
+}
613
+
614
+static int sig_dir_sort (const void *a, const void *b)
615
+{
616
+  ENTRY_DIR *pa = (ENTRY_DIR *) a;
617
+  ENTRY_DIR *pb = (ENTRY_DIR *) b;
618
+
619
+  return (mutt_strcmp (pa->data->name, pb->data->name));
620
+}
621
+
622
+static int sig_dir_menu (char *path, char *msg_file)
623
+{
624
+  MUTTMENU *menu;
625
+  SIG_LIST *sigl;
626
+  LIST *result = NULL;
627
+  ENTRY_DIR *FileTable;
628
+  SIG_DIR *list, *files;
629
+  char buf[STRING], helpstr[SHORT_STRING], title[SHORT_STRING];
630
+  int i, done = 0;
631
+
632
+  if ((list = sig_directory (path)) == NULL)
633
+    return -1;
634
+
635
+  snprintf (title, sizeof (title), "Signature directory : %s", path);
636
+
637
+  menu = mutt_new_menu ();
638
+  menu->make_entry = sig_dir_make_entry;
639
+  menu->search = NULL; /* search within files with sig_search_filter() */
640
+  menu->tag = sig_dir_tag;
641
+  menu->menu = MENU_SIG_DIR;
642
+  menu->title = title;
643
+  menu->help = mutt_compile_help (helpstr, sizeof (helpstr),
644
+				  MENU_SIG_DIR, SigDirHelp);
645
+
646
+  for (files = list; files; files = files->next)
647
+    menu->max++;
648
+
649
+  menu->data = FileTable = (ENTRY_DIR *) safe_calloc (menu->max,
650
+						      sizeof (ENTRY_DIR));
651
+
652
+  for (i = 0, files = list; files; i++, files = files->next)
653
+    FileTable[i].data = files;
654
+
655
+  qsort (FileTable, menu->max, sizeof (ENTRY_DIR), sig_dir_sort);
656
+
657
+  while (!done)
658
+  {
659
+    switch (mutt_menuLoop (menu))
660
+    {
661
+      case OP_SIG_SEARCH:
662
+	sigl = sig_search_filter (menu, path);
663
+
664
+	if (sigl)
665
+	{
666
+	  if ((result = sig_list_menu (_("query results"), sigl)) != NULL)
667
+	  {
668
+	    append_signature (msg_file, result);
669
+	    done = 1;
670
+	  }
671
+
672
+	  MAYBE_REDRAW (menu->redraw);
673
+	  free_sig_list (&sigl);
674
+	}
675
+	break;
676
+
677
+      case OP_GENERIC_SELECT_ENTRY:
678
+	snprintf (buf, sizeof (buf), "%s/%s", path,
679
+		  FileTable[menu->current].data->name);
680
+	sigl = NULL;
681
+	read_sig_file (buf, &sigl, NULL);
682
+
683
+	if (sigl)
684
+	{
685
+	  if ((result = sig_list_menu (buf, sigl)) != NULL)
686
+	  {
687
+	    append_signature (msg_file, result);
688
+	    done = 1;
689
+	  }
690
+
691
+	  MAYBE_REDRAW (menu->redraw);
692
+	  free_sig_list (&sigl);
693
+      	}
694
+	break;
695
+
696
+      case OP_EXIT:
697
+        done = 1;
698
+        break;
699
+    }
700
+  }
701
+
702
+  while (list)
703
+  {
704
+    safe_free ((void **)&list->name);
705
+    files = list;
706
+    list = list->next;
707
+    safe_free ((void **)&files);
708
+  }
709
+  safe_free ((void **)&FileTable);
710
+  mutt_menuDestroy (&menu);
711
+  return 0;
712
+}
713
+
714
+void mutt_signature (char *msg_file)
715
+{
716
+  if (!SigDirectory)
717
+  {
718
+    mutt_error (_("variable 'signatures_directory' is unset"));
719
+    return;
720
+  }
721
+
722
+  if (sig_dir_menu (SigDirectory, msg_file) == -1)
723
+    mutt_error (_("%s: no files in this directory"), SigDirectory);
724
+  else
725
+    set_option (OPTNEEDREDRAW);
726
+}

Return to bug 94542