NeoMutt  2024-02-01-25-ga71e95
Teaching an old dog new tricks
No Matches
dlg_query.c File Reference

Routines for querying an external address book. More...

#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "editor/lib.h"
#include "history/lib.h"
#include "key/lib.h"
#include "menu/lib.h"
#include "pattern/lib.h"
#include "send/lib.h"
#include "alias.h"
#include "format_flags.h"
#include "functions.h"
#include "globals.h"
#include "gui.h"
#include "mutt_logging.h"
#include "muttlib.h"
+ Include dependency graph for dlg_query.c:

Go to the source code of this file.


bool alias_to_addrlist (struct AddressList *al, struct Alias *alias)
 Turn an Alias into an AddressList.
static const char * query_format_str (char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
 Format a string for the query menu - Implements format_t -.
static void query_make_entry (struct Menu *menu, int line, struct Buffer *buf)
 Format an Alias for the Menu - Implements Menu::make_entry() -.
static int query_tag (struct Menu *menu, int sel, int act)
 Tag an entry in the Query Menu - Implements Menu::tag() -.
int query_run (const char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
 Run an external program to find Addresses.
static int query_window_observer (struct NotifyCallback *nc)
 Notification that a Window has changed - Implements observer_t -.
static struct MuttWindowquery_dialog_new (struct AliasMenuData *mdata, const char *query)
 Create an Query Selection Dialog.
static bool dlg_query (struct Buffer *buf, struct AliasMenuData *mdata)
 Get the user to enter an Address Query -.
int query_complete (struct Buffer *buf, struct ConfigSubset *sub)
 Perform auto-complete using an Address Query.
void query_index (struct Mailbox *m, struct ConfigSubset *sub)
 Perform an Alias Query and display the results.


static const struct Mapping QueryHelp []
 Help Bar for the Address Query dialog.

Detailed Description

Routines for querying an external address book.

  • Richard Russon
  • Pietro Cerutti
  • Dennis Schön

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, see

Definition in file dlg_query.c.

Function Documentation

◆ alias_to_addrlist()

bool alias_to_addrlist ( struct AddressList *  al,
struct Alias alias 

Turn an Alias into an AddressList.

alAddressList to fill (must be empty)
aliasAlias to use
Return values

Definition at line 120 of file dlg_query.c.

122 if (!al || !TAILQ_EMPTY(al) || !alias)
123 return false;
125 mutt_addrlist_copy(al, &alias->addr, false);
126 if (!TAILQ_EMPTY(al))
127 {
128 struct Address *first = TAILQ_FIRST(al);
129 struct Address *second = TAILQ_NEXT(first, entries);
130 if (!second && !first->personal)
131 {
132 first->personal = buf_new(alias->name);
133 }
135 mutt_addrlist_to_intl(al, NULL);
136 }
138 return true;
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:765
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1297
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition: buffer.c:321
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
#define TAILQ_EMPTY(head)
Definition: queue.h:721
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
char * name
Short name.
Definition: alias.h:36
struct AddressList addr
List of Addresses the Alias expands to.
Definition: alias.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_run()

int query_run ( const char *  s,
bool  verbose,
struct AliasList *  al,
const struct ConfigSubset sub 

Run an external program to find Addresses.

sString to match
verboseIf true, print progress messages
alAlias list to fill
subConfig items
Return values

Definition at line 269 of file dlg_query.c.

271 FILE *fp = NULL;
272 char *buf = NULL;
273 size_t buflen;
274 char *msg = NULL;
275 size_t msglen = 0;
276 char *p = NULL;
277 struct Buffer *cmd = buf_pool_get();
279 const char *const c_query_command = cs_subset_string(sub, "query_command");
280 buf_file_expand_fmt_quote(cmd, c_query_command, s);
282 pid_t pid = filter_create(buf_string(cmd), NULL, &fp, NULL, EnvList);
283 if (pid < 0)
284 {
285 mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", buf_string(cmd));
286 buf_pool_release(&cmd);
287 return -1;
288 }
289 buf_pool_release(&cmd);
291 if (verbose)
292 mutt_message(_("Waiting for response..."));
294 /* The query protocol first reads one NL-terminated line. If an error
295 * occurs, this is assumed to be an error message. Otherwise it's ignored. */
296 msg = mutt_file_read_line(msg, &msglen, fp, NULL, MUTT_RL_NO_FLAGS);
297 while ((buf = mutt_file_read_line(buf, &buflen, fp, NULL, MUTT_RL_NO_FLAGS)))
298 {
299 p = strtok(buf, "\t\n");
300 if (p)
301 {
302 struct Alias *alias = alias_new();
304 mutt_addrlist_parse(&alias->addr, p);
305 p = strtok(NULL, "\t\n");
306 if (p)
307 {
308 alias->name = mutt_str_dup(p);
309 p = strtok(NULL, "\t\n");
310 parse_alias_comments(alias, p);
311 }
312 TAILQ_INSERT_TAIL(al, alias, entries);
313 }
314 }
315 FREE(&buf);
316 mutt_file_fclose(&fp);
317 if (filter_wait(pid))
318 {
319 mutt_debug(LL_DEBUG1, "Error: %s\n", msg);
320 if (verbose)
321 mutt_error("%s", msg);
322 }
323 else
324 {
325 if (verbose)
326 mutt_message("%s", msg);
327 }
328 FREE(&msg);
330 return 0;
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:480
void parse_alias_comments(struct Alias *alias, const char *com)
Parse the alias/query comment field.
Definition: commands.c:95
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:665
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:801
void buf_file_expand_fmt_quote(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1497
#define mutt_file_fclose(FP)
Definition: file.h:148
No flags are set.
Definition: file.h:40
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:219
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, char **envlist)
Set up filter program.
Definition: filter.c:208
char ** EnvList
Private copy of the environment variables.
Definition: globals.c:78
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
Log at debug level 1.
Definition: logging2.h:43
#define FREE(x)
Definition: memory.h:45
#define _(a)
Definition: message.h:28
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:253
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
A shortcut for an email address or addresses.
Definition: alias.h:35
String manipulation buffer.
Definition: buffer.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_dialog_new()

static struct MuttWindow * query_dialog_new ( struct AliasMenuData mdata,
const char *  query 

Create an Query Selection Dialog.

mdataMenu data holding Aliases
queryInitial query string
Return values
ptrNew Dialog

Definition at line 365 of file dlg_query.c.

369 struct Menu *menu = dlg->wdata;
372 menu->tag = query_tag;
373 menu->max = ARRAY_SIZE(&mdata->ava);
374 mdata->title = mutt_str_dup(_("Query"));
375 menu->mdata = mdata;
376 menu->mdata_free = NULL; // Menu doesn't own the data
378 struct MuttWindow *win_menu = menu->win;
380 // Override the Simple Dialog's recalc()
381 win_menu->recalc = alias_recalc;
383 char title[256] = { 0 };
384 snprintf(title, sizeof(title), "%s: %s", mdata->title, query);
385 struct MuttWindow *sbar = window_find_child(dlg, WT_STATUS_BAR);
386 sbar_set_title(sbar, title);
388 // NT_COLOR is handled by the SimpleDialog
392 return dlg;
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:87
static const struct Mapping QueryHelp[]
Help Bar for the Address Query dialog.
Definition: dlg_query.c:100
static void query_make_entry(struct Menu *menu, int line, struct Buffer *buf)
Format an Alias for the Menu - Implements Menu::make_entry() -.
Definition: dlg_query.c:233
static int query_tag(struct Menu *menu, int sel, int act)
Tag an entry in the Query Menu - Implements Menu::tag() -.
Definition: dlg_query.c:248
static int query_window_observer(struct NotifyCallback *nc)
Notification that a Window has changed - Implements observer_t -.
Definition: dlg_query.c:336
int alias_config_observer(struct NotifyCallback *nc)
Notification that a Config Variable has changed - Implements observer_t -.
Definition: gui.c:43
int alias_recalc(struct MuttWindow *win)
Recalculate the display of the Alias Window - Implements MuttWindow::recalc() -.
Definition: gui.c:89
struct MuttWindow * simple_dialog_new(enum MenuType mtype, enum WindowType wtype, const struct Mapping *help_data)
Create a simple index Dialog.
Definition: simple.c:132
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:191
struct MuttWindow * window_find_child(struct MuttWindow *win, enum WindowType type)
Recursively find a child Window of a given type.
Definition: mutt_window.c:533
Query Dialog, dlg_query()
Definition: mutt_window.h:90
Status Bar containing extra info about the Index/Pager/etc.
Definition: mutt_window.h:102
MuttWindow has changed, NotifyWindow, EventWindow.
Definition: notify_type.h:57
Config has changed, NotifyConfig, EventConfig.
Definition: notify_type.h:43
void sbar_set_title(struct MuttWindow *win, const char *title)
Set the title for the Simple Bar.
Definition: sbar.c:227
char * title
Title for the status bar.
Definition: gui.h:62
struct Notify * notify
Notifications: NotifyConfig, EventConfig.
Definition: subset.h:52
Definition: lib.h:69
struct MuttWindow * win
Window holding the Menu.
Definition: lib.h:76
void(* mdata_free)(struct Menu *menu, void **ptr)
Definition: lib.h:149
int(* tag)(struct Menu *menu, int sel, int act)
Definition: lib.h:119
void * mdata
Private data.
Definition: lib.h:135
void(* make_entry)(struct Menu *menu, int line, struct Buffer *buf)
Definition: lib.h:94
int max
Number of entries in the menu.
Definition: lib.h:71
void * wdata
Private data.
Definition: mutt_window.h:145
struct Notify * notify
Notifications: NotifyWindow, EventWindow.
Definition: mutt_window.h:138
int(* recalc)(struct MuttWindow *win)
Definition: mutt_window.h:173
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
Select from results of external query.
Definition: type.h:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_complete()

int query_complete ( struct Buffer buf,
struct ConfigSubset sub 

Perform auto-complete using an Address Query.

bufBuffer for completion
subConfig item
Return values

Definition at line 465 of file dlg_query.c.

467 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
468 mdata.search_state = search_state_new();
470 struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
471 const char *const c_query_command = cs_subset_string(sub, "query_command");
472 if (!c_query_command)
473 {
474 mutt_warning(_("Query command not defined"));
475 goto done;
476 }
478 query_run(buf_string(buf), true, &al, sub);
479 if (TAILQ_EMPTY(&al))
480 goto done;
482 = &al;
484 struct Alias *a_first = TAILQ_FIRST(&al);
485 if (!TAILQ_NEXT(a_first, entries)) // only one response?
486 {
487 struct AddressList addr = TAILQ_HEAD_INITIALIZER(addr);
488 if (alias_to_addrlist(&addr, a_first))
489 {
491 buf_reset(buf);
492 mutt_addrlist_write(&addr, buf, false);
493 mutt_addrlist_clear(&addr);
495 }
496 goto done;
497 }
499 struct Alias *np = NULL;
500 TAILQ_FOREACH(np,, entries)
501 {
502 alias_array_alias_add(&mdata.ava, np);
503 }
505 /* multiple results, choose from query menu */
506 if (!dlg_query(buf, &mdata))
507 goto done;
509 buf_reset(buf);
510 buf_alloc(buf, 8192);
511 bool first = true;
512 struct AliasView *avp = NULL;
513 ARRAY_FOREACH(avp, &mdata.ava)
514 {
515 if (!avp->is_tagged)
516 continue;
518 if (!first)
519 {
520 buf_addstr(buf, ", ");
521 }
523 first = false;
524 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
525 if (alias_to_addrlist(&al_copy, avp->alias))
526 {
527 mutt_addrlist_to_local(&al_copy);
528 mutt_addrlist_write(&al_copy, buf, false);
529 mutt_addrlist_clear(&al_copy);
530 }
531 }
534 ARRAY_FREE(&mdata.ava);
535 FREE(&mdata.title);
536 FREE(&mdata.limit);
538 aliaslist_clear(&al);
539 return 0;
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1464
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1382
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1210
void aliaslist_clear(struct AliasList *al)
Empty a List of Aliases.
Definition: alias.c:702
int alias_array_alias_add(struct AliasViewArray *ava, struct Alias *alias)
Add an Alias to the AliasViewArray.
Definition: array.c:47
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
#define ARRAY_FREE(head)
Release all memory.
Definition: array.h:204
Static initializer for arrays.
Definition: array.h:58
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:93
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:243
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:354
int query_run(const char *s, bool verbose, struct AliasList *al, const struct ConfigSubset *sub)
Run an external program to find Addresses.
Definition: dlg_query.c:269
bool alias_to_addrlist(struct AddressList *al, struct Alias *alias)
Turn an Alias into an AddressList.
Definition: dlg_query.c:120
static bool dlg_query(struct Buffer *buf, struct AliasMenuData *mdata)
Get the user to enter an Address Query -.
Definition: dlg_query.c:406
#define mutt_warning(...)
Definition: logging2.h:90
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
Definition: queue.h:637
void search_state_free(struct SearchState **ptr)
Free a SearchState.
Definition: search_state.c:51
struct SearchState * search_state_new(void)
Create a new SearchState.
Definition: search_state.c:39
AliasView array wrapper with Pattern information -.
Definition: gui.h:54
char * limit
Limit being used.
Definition: gui.h:60
struct AliasViewArray ava
All Aliases/Queries.
Definition: gui.h:55
struct SearchState * search_state
State of the current search.
Definition: gui.h:63
struct AliasList * al
Alias data.
Definition: gui.h:56
struct ConfigSubset * sub
Config items.
Definition: gui.h:57
GUI data wrapping an Alias.
Definition: gui.h:38
struct Alias * alias
Definition: gui.h:46
bool is_tagged
Is it tagged?
Definition: gui.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_index()

void query_index ( struct Mailbox m,
struct ConfigSubset sub 

Perform an Alias Query and display the results.

subConfig item

Definition at line 547 of file dlg_query.c.

549 const char *const c_query_command = cs_subset_string(sub, "query_command");
550 if (!c_query_command)
551 {
552 mutt_warning(_("Query command not defined"));
553 return;
554 }
556 struct AliasList al = TAILQ_HEAD_INITIALIZER(al);
557 struct AliasMenuData mdata = { ARRAY_HEAD_INITIALIZER, NULL, sub };
558 = &al;
559 mdata.search_state = search_state_new();
561 struct Buffer *buf = buf_pool_get();
562 if ((mw_get_field(_("Query: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
563 buf_is_empty(buf))
564 {
565 goto done;
566 }
568 query_run(buf_string(buf), false, &al, sub);
569 if (TAILQ_EMPTY(&al))
570 goto done;
572 struct Alias *np = NULL;
573 TAILQ_FOREACH(np,, entries)
574 {
575 alias_array_alias_add(&mdata.ava, np);
576 }
578 if (!dlg_query(buf, &mdata))
579 goto done;
581 // Prepare the "To:" field of a new email
582 struct Email *e = email_new();
583 e->env = mutt_env_new();
585 struct AliasView *avp = NULL;
586 ARRAY_FOREACH(avp, &mdata.ava)
587 {
588 if (!avp->is_tagged)
589 continue;
591 struct AddressList al_copy = TAILQ_HEAD_INITIALIZER(al_copy);
592 if (alias_to_addrlist(&al_copy, avp->alias))
593 {
594 mutt_addrlist_copy(&e->env->to, &al_copy, false);
595 mutt_addrlist_clear(&al_copy);
596 }
597 }
599 mutt_send_message(SEND_REVIEW_TO, e, NULL, m, NULL, sub);
602 ARRAY_FREE(&mdata.ava);
603 FREE(&mdata.title);
604 FREE(&mdata.limit);
606 aliaslist_clear(&al);
607 buf_pool_release(&buf);
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:308
struct Email * email_new(void)
Create a new Email.
Definition: email.c:80
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:46
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:274
Miscellaneous strings.
Definition: lib.h:56
No flags are set.
Definition: mutt.h:56
int mutt_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Mailbox *m, struct EmailArray *ea, struct ConfigSubset *sub)
Send an email.
Definition: send.c:2115
Allow the user to edit the To field.
Definition: send.h:56
The envelope/body of an email.
Definition: email.h:39
struct Envelope * env
Envelope information.
Definition: email.h:68
struct AddressList to
Email's 'To' list.
Definition: envelope.h:60
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ QueryHelp

const struct Mapping QueryHelp[]
Initial value:
= {
{ N_("Exit"), OP_EXIT },
{ N_("Mail"), OP_MAIL },
{ N_("New Query"), OP_QUERY },
{ N_("Make Alias"), OP_CREATE_ALIAS },
{ N_("Sort"), OP_SORT },
{ N_("Rev-Sort"), OP_SORT_REVERSE },
{ N_("Search"), OP_SEARCH },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
#define N_(a)
Definition: message.h:32

Help Bar for the Address Query dialog.

Definition at line 100 of file dlg_query.c.