NeoMutt  2020-03-20-65-g141838
Teaching an old dog new tricks
DOXYGEN
query.c File Reference

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

#include "config.h"
#include <regex.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "email/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "query.h"
#include "alias.h"
#include "format_flags.h"
#include "globals.h"
#include "keymap.h"
#include "mutt_logging.h"
#include "mutt_menu.h"
#include "muttlib.h"
#include "opcodes.h"
#include "send.h"
+ Include dependency graph for query.c:

Go to the source code of this file.

Data Structures

struct  Query
 An entry from an external address-book. More...
 
struct  QueryEntry
 An entry in a selectable list of Query's. More...
 

Functions

static bool result_to_addr (struct AddressList *al, struct Query *r)
 Turn a Query into an AddressList. More...
 
static struct Queryquery_new (void)
 Create a new query. More...
 
static void query_free (struct Query **query)
 Free a Query. More...
 
static struct Queryrun_query (char *s, int quiet)
 Run an external program to find Addresses. More...
 
static int query_search (struct Menu *menu, regex_t *rx, int line)
 Search a Address menu item - Implements Menu::search() More...
 
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, unsigned long data, MuttFormatFlags flags)
 Format a string for the query menu - Implements format_t. More...
 
static void query_make_entry (char *buf, size_t buflen, struct Menu *menu, int line)
 Format a menu item for the query list - Implements Menu::make_entry() More...
 
static int query_tag (struct Menu *menu, int sel, int act)
 Tag an entry in the Query Menu - Implements Menu::tag() More...
 
static void query_menu (char *buf, size_t buflen, struct Query *results, bool retbuf)
 Get the user to enter an Address Query. More...
 
int mutt_query_complete (char *buf, size_t buflen)
 Perform auto-complete using an Address Query. More...
 
void mutt_query_menu (char *buf, size_t buflen)
 Show the user the results of a Query. More...
 

Variables

char * C_QueryCommand
 Config: External command to query and external address book. More...
 
char * C_QueryFormat
 Config: printf-like format string for the query menu (address book) More...
 
static const struct Mapping QueryHelp []
 

Detailed Description

Routines for querying and external address book.

Authors
  • Michael R. Elkins
  • Pietro Cerutti

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 http://www.gnu.org/licenses/.

Definition in file query.c.

Function Documentation

◆ result_to_addr()

static bool result_to_addr ( struct AddressList *  al,
struct Query r 
)
static

Turn a Query into an AddressList.

Parameters
alAddressList to fill (must be empty)
rQuery to use
Return values
boolTrue on success

Definition at line 93 of file query.c.

94 {
95  if (!al || !TAILQ_EMPTY(al) || !r)
96  return false;
97 
98  mutt_addrlist_copy(al, &r->addr, false);
99  if (!TAILQ_EMPTY(al))
100  {
101  struct Address *first = TAILQ_FIRST(al);
102  struct Address *second = TAILQ_NEXT(first, entries);
103  if (!second && !first->personal)
104  first->personal = mutt_str_strdup(r->name);
105 
106  mutt_addrlist_to_intl(al, NULL);
107  }
108 
109  return true;
110 }
#define TAILQ_FIRST(head)
Definition: queue.h:716
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:728
char * name
Definition: query.c:63
An email address.
Definition: address.h:34
char * personal
Real name of address.
Definition: address.h:36
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1217
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
#define TAILQ_EMPTY(head)
Definition: queue.h:714
struct AddressList addr
Definition: query.c:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_new()

static struct Query* query_new ( void  )
static

Create a new query.

Return values
Anewly allocated query

Definition at line 116 of file query.c.

117 {
118  struct Query *query = mutt_mem_calloc(1, sizeof(struct Query));
119  TAILQ_INIT(&query->addr);
120  return query;
121 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define TAILQ_INIT(head)
Definition: queue.h:758
An entry from an external address-book.
Definition: query.c:59
struct AddressList addr
Definition: query.c:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_free()

static void query_free ( struct Query **  query)
static

Free a Query.

Parameters
[out]queryQuery to free

Definition at line 127 of file query.c.

128 {
129  if (!query)
130  return;
131 
132  struct Query *p = NULL;
133 
134  while (*query)
135  {
136  p = *query;
137  *query = (*query)->next;
138 
140  FREE(&p->name);
141  FREE(&p->other);
142  FREE(&p);
143  }
144 }
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1382
char * name
Definition: query.c:63
struct Query * next
Definition: query.c:65
char * other
Definition: query.c:64
An entry from an external address-book.
Definition: query.c:59
#define FREE(x)
Definition: memory.h:40
struct AddressList addr
Definition: query.c:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ run_query()

static struct Query* run_query ( char *  s,
int  quiet 
)
static

Run an external program to find Addresses.

Parameters
sString to match
quietIf true, don't print progress messages
Return values
ptrQuery List of results

Definition at line 152 of file query.c.

153 {
154  FILE *fp = NULL;
155  struct Query *first = NULL;
156  struct Query *cur = NULL;
157  char *buf = NULL;
158  size_t buflen;
159  int dummy = 0;
160  char *msg = NULL;
161  size_t msglen = 0;
162  char *p = NULL;
163  pid_t pid;
164  struct Buffer *cmd = mutt_buffer_pool_get();
165 
167 
168  pid = filter_create(mutt_b2s(cmd), NULL, &fp, NULL);
169  if (pid < 0)
170  {
171  mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", mutt_b2s(cmd));
173  return 0;
174  }
176 
177  if (!quiet)
178  mutt_message(_("Waiting for response..."));
179 
180  /* The query protocol first reads one NL-terminated line. If an error
181  * occurs, this is assumed to be an error message. Otherwise it's ignored. */
182  msg = mutt_file_read_line(msg, &msglen, fp, &dummy, 0);
183  while ((buf = mutt_file_read_line(buf, &buflen, fp, &dummy, 0)))
184  {
185  p = strtok(buf, "\t\n");
186  if (p)
187  {
188  if (first)
189  {
190  cur->next = query_new();
191  cur = cur->next;
192  }
193  else
194  {
195  first = query_new();
196  cur = first;
197  }
198 
199  mutt_addrlist_parse(&cur->addr, p);
200  p = strtok(NULL, "\t\n");
201  if (p)
202  {
203  cur->name = mutt_str_strdup(p);
204  p = strtok(NULL, "\t\n");
205  if (p)
206  cur->other = mutt_str_strdup(p);
207  }
208  }
209  }
210  FREE(&buf);
211  mutt_file_fclose(&fp);
212  if (filter_wait(pid))
213  {
214  mutt_debug(LL_DEBUG1, "Error: %s\n", msg);
215  if (!quiet)
216  mutt_error("%s", msg);
217  }
218  else
219  {
220  if (!quiet)
221  mutt_message("%s", msg);
222  }
223  FREE(&msg);
224 
225  return first;
226 }
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:458
#define mutt_message(...)
Definition: logging.h:83
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
char * name
Definition: query.c:63
#define _(a)
Definition: message.h:28
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, int flags)
Read a line from a file.
Definition: file.c:667
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Query * next
Definition: query.c:65
#define mutt_b2s(buf)
Definition: buffer.h:41
char * other
Definition: query.c:64
An entry from an external address-book.
Definition: query.c:59
Log at debug level 1.
Definition: logging.h:40
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
#define mutt_error(...)
Definition: logging.h:84
void mutt_buffer_file_expand_fmt_quote(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1426
#define FREE(x)
Definition: memory.h:40
static struct Query * query_new(void)
Create a new query.
Definition: query.c:116
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
char * C_QueryCommand
Config: External command to query and external address book.
Definition: query.c:53
struct AddressList addr
Definition: query.c:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_search()

static int query_search ( struct Menu menu,
regex_t *  rx,
int  line 
)
static

Search a Address menu item - Implements Menu::search()

Try to match various Address fields.

Definition at line 233 of file query.c.

234 {
235  struct QueryEntry *table = menu->data;
236  struct Query *query = table[line].data;
237 
238  if (query->name && !regexec(rx, query->name, 0, NULL, 0))
239  return 0;
240  if (query->other && !regexec(rx, query->other, 0, NULL, 0))
241  return 0;
242  if (!TAILQ_EMPTY(&query->addr))
243  {
244  struct Address *addr = TAILQ_FIRST(&query->addr);
245  if (addr->personal && !regexec(rx, addr->personal, 0, NULL, 0))
246  {
247  return 0;
248  }
249  if (addr->mailbox && !regexec(rx, addr->mailbox, 0, NULL, 0))
250  {
251  return 0;
252  }
253  }
254 
255  return REG_NOMATCH;
256 }
#define TAILQ_FIRST(head)
Definition: queue.h:716
char * name
Definition: query.c:63
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
struct Query * data
Definition: query.c:74
char * other
Definition: query.c:64
An entry from an external address-book.
Definition: query.c:59
char * personal
Real name of address.
Definition: address.h:36
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
#define TAILQ_EMPTY(head)
Definition: queue.h:714
int const char int line
Definition: acutest.h:602
struct AddressList addr
Definition: query.c:62
An entry in a selectable list of Query&#39;s.
Definition: query.c:71
+ Here is the caller graph for this function:

◆ query_format_str()

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,
unsigned long  data,
MuttFormatFlags  flags 
)
static

Format a string for the query menu - Implements format_t.

Expando Description
%a Destination address
%c Current entry number
%e Extra information
%n Destination name
%t * if current entry is tagged, a space otherwise

Definition at line 269 of file query.c.

273 {
274  struct QueryEntry *entry = (struct QueryEntry *) data;
275  struct Query *query = entry->data;
276  char fmt[128];
277  char tmp[256] = { 0 };
278  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
279 
280  switch (op)
281  {
282  case 'a':
283  mutt_addrlist_write(&query->addr, tmp, sizeof(tmp), true);
284  mutt_format_s(buf, buflen, prec, tmp);
285  break;
286  case 'c':
287  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
288  snprintf(buf, buflen, fmt, query->num + 1);
289  break;
290  case 'e':
291  if (!optional)
292  mutt_format_s(buf, buflen, prec, NONULL(query->other));
293  else if (!query->other || !*query->other)
294  optional = false;
295  break;
296  case 'n':
297  mutt_format_s(buf, buflen, prec, NONULL(query->name));
298  break;
299  case 't':
300  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
301  snprintf(buf, buflen, fmt, entry->tagged ? '*' : ' ');
302  break;
303  default:
304  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
305  snprintf(buf, buflen, fmt, op);
306  break;
307  }
308 
309  if (optional)
310  {
311  mutt_expando_format(buf, buflen, col, cols, if_str, query_format_str, data,
313  }
314  else if (flags & MUTT_FORMAT_OPTIONAL)
315  {
316  mutt_expando_format(buf, buflen, col, cols, else_str, query_format_str,
317  data, MUTT_FORMAT_NO_FLAGS);
318  }
319 
320  return src;
321 }
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:863
#define NONULL(x)
Definition: string2.h:37
static int const char * fmt
Definition: acutest.h:473
char * name
Definition: query.c:63
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
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, unsigned long data, MuttFormatFlags flags)
Format a string for the query menu - Implements format_t.
Definition: query.c:269
struct Query * data
Definition: query.c:74
int num
Definition: query.c:61
bool tagged
Definition: query.c:73
char * other
Definition: query.c:64
An entry from an external address-book.
Definition: query.c:59
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:1222
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
struct AddressList addr
Definition: query.c:62
An entry in a selectable list of Query&#39;s.
Definition: query.c:71
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1138
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_make_entry()

static void query_make_entry ( char *  buf,
size_t  buflen,
struct Menu menu,
int  line 
)
static

Format a menu item for the query list - Implements Menu::make_entry()

Definition at line 326 of file query.c.

327 {
328  struct QueryEntry *entry = &((struct QueryEntry *) menu->data)[line];
329 
330  entry->data->num = line;
331  mutt_expando_format(buf, buflen, 0, menu->win_index->state.cols,
333  (unsigned long) entry, MUTT_FORMAT_ARROWCURSOR);
334 }
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags)
Expand expandos (x) in a string.
Definition: muttlib.c:863
#define NONULL(x)
Definition: string2.h:37
#define MUTT_FORMAT_ARROWCURSOR
Reserve space for arrow_cursor.
Definition: format_flags.h:35
char * C_QueryFormat
Config: printf-like format string for the query menu (address book)
Definition: query.c:54
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, unsigned long data, MuttFormatFlags flags)
Format a string for the query menu - Implements format_t.
Definition: query.c:269
struct Query * data
Definition: query.c:74
int num
Definition: query.c:61
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:58
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:93
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
int const char int line
Definition: acutest.h:602
struct MuttWindow * win_index
Definition: mutt_menu.h:95
An entry in a selectable list of Query&#39;s.
Definition: query.c:71
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ query_tag()

static int query_tag ( struct Menu menu,
int  sel,
int  act 
)
static

Tag an entry in the Query Menu - Implements Menu::tag()

Definition at line 339 of file query.c.

340 {
341  struct QueryEntry *cur = &((struct QueryEntry *) menu->data)[sel];
342  bool ot = cur->tagged;
343 
344  cur->tagged = ((act >= 0) ? act : !cur->tagged);
345  return cur->tagged - ot;
346 }
bool tagged
Definition: query.c:73
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
An entry in a selectable list of Query&#39;s.
Definition: query.c:71
+ Here is the caller graph for this function:

◆ query_menu()

static void query_menu ( char *  buf,
size_t  buflen,
struct Query results,
bool  retbuf 
)
static

Get the user to enter an Address Query.

Parameters
bufBuffer for the query
buflenLength of buffer
resultsQuery List
retbufIf true, populate the results

Definition at line 355 of file query.c.

356 {
357  struct Menu *menu = NULL;
358  struct QueryEntry *query_table = NULL;
359  struct Query *queryp = NULL;
360  char title[256];
361 
362  if (!results)
363  {
364  /* Prompt for Query */
365  if ((mutt_get_field(_("Query: "), buf, buflen, MUTT_COMP_NO_FLAGS) == 0) &&
366  (buf[0] != '\0'))
367  {
368  results = run_query(buf, 0);
369  if (!results)
370  return;
371  }
372  }
373 
374  snprintf(title, sizeof(title), _("Query '%s'"), buf);
375 
376  struct MuttWindow *dlg =
379 #ifdef USE_DEBUG_WINDOW
380  dlg->name = "query";
381 #endif
382  dlg->type = WT_DIALOG;
383  struct MuttWindow *index =
386  index->type = WT_INDEX;
387  struct MuttWindow *ibar = mutt_window_new(
389  ibar->type = WT_INDEX_BAR;
390 
391  if (C_StatusOnTop)
392  {
393  mutt_window_add_child(dlg, ibar);
394  mutt_window_add_child(dlg, index);
395  }
396  else
397  {
398  mutt_window_add_child(dlg, index);
399  mutt_window_add_child(dlg, ibar);
400  }
401 
402  dialog_push(dlg);
403 
404  menu = mutt_menu_new(MENU_QUERY);
405 
406  menu->pagelen = index->state.rows;
407  menu->win_index = index;
408  menu->win_ibar = ibar;
409 
411  menu->search = query_search;
412  menu->tag = query_tag;
413  menu->title = title;
414  char helpstr[1024];
415  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_QUERY, QueryHelp);
417 
418  /* count the number of results */
419  for (queryp = results; queryp; queryp = queryp->next)
420  menu->max++;
421 
422  query_table = mutt_mem_calloc(menu->max, sizeof(struct QueryEntry));
423  menu->data = query_table;
424 
425  queryp = results;
426  for (int i = 0; queryp; queryp = queryp->next, i++)
427  query_table[i].data = queryp;
428 
429  int done = 0;
430  while (done == 0)
431  {
432  const int op = mutt_menu_loop(menu);
433  switch (op)
434  {
435  case OP_QUERY_APPEND:
436  case OP_QUERY:
437  if ((mutt_get_field(_("Query: "), buf, buflen, MUTT_COMP_NO_FLAGS) != 0) ||
438  (buf[0] == '\0'))
439  {
440  break;
441  }
442 
443  struct Query *newresults = run_query(buf, 0);
444 
445  menu->redraw = REDRAW_FULL;
446  if (newresults)
447  {
448  snprintf(title, sizeof(title), _("Query '%s'"), buf);
449 
450  if (op == OP_QUERY)
451  {
452  query_free(&results);
453  results = newresults;
454  FREE(&query_table);
455  }
456  else
457  {
458  /* append */
459  for (queryp = results; queryp->next; queryp = queryp->next)
460  ;
461 
462  queryp->next = newresults;
463  }
464 
465  menu->current = 0;
466  mutt_menu_pop_current(menu);
467  mutt_menu_free(&menu);
468  menu = mutt_menu_new(MENU_QUERY);
469 
470  menu->pagelen = index->state.rows;
471  menu->win_index = index;
472  menu->win_ibar = ibar;
473 
475  menu->search = query_search;
476  menu->tag = query_tag;
477  menu->title = title;
478  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_QUERY, QueryHelp);
480 
481  /* count the number of results */
482  for (queryp = results; queryp; queryp = queryp->next)
483  menu->max++;
484 
485  if (op == OP_QUERY)
486  {
487  menu->data = query_table =
488  mutt_mem_calloc(menu->max, sizeof(struct QueryEntry));
489 
490  queryp = results;
491  for (int i = 0; queryp; queryp = queryp->next, i++)
492  query_table[i].data = queryp;
493  }
494  else
495  {
496  bool clear = false;
497 
498  /* append */
499  mutt_mem_realloc(&query_table, menu->max * sizeof(struct QueryEntry));
500 
501  menu->data = query_table;
502 
503  queryp = results;
504  for (int i = 0; queryp; queryp = queryp->next, i++)
505  {
506  /* once we hit new entries, clear/init the tag */
507  if (queryp == newresults)
508  clear = true;
509 
510  query_table[i].data = queryp;
511  if (clear)
512  query_table[i].tagged = false;
513  }
514  }
515  }
516  break;
517 
518  case OP_CREATE_ALIAS:
519  if (menu->tagprefix)
520  {
521  struct AddressList naddr = TAILQ_HEAD_INITIALIZER(naddr);
522 
523  for (int i = 0; i < menu->max; i++)
524  {
525  if (query_table[i].tagged)
526  {
527  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
528  if (result_to_addr(&al, query_table[i].data))
529  {
530  mutt_addrlist_copy(&naddr, &al, false);
531  mutt_addrlist_clear(&al);
532  }
533  }
534  }
535 
536  mutt_alias_create(NULL, &naddr);
537  mutt_addrlist_clear(&naddr);
538  }
539  else
540  {
541  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
542  if (result_to_addr(&al, query_table[menu->current].data))
543  {
544  mutt_alias_create(NULL, &al);
545  mutt_addrlist_clear(&al);
546  }
547  }
548  break;
549 
550  case OP_GENERIC_SELECT_ENTRY:
551  if (retbuf)
552  {
553  done = 2;
554  break;
555  }
556  /* fallthrough */
557  case OP_MAIL:
558  {
559  struct Email *e = email_new();
560  e->env = mutt_env_new();
561  if (!menu->tagprefix)
562  {
563  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
564  if (result_to_addr(&al, query_table[menu->current].data))
565  {
566  mutt_addrlist_copy(&e->env->to, &al, false);
567  mutt_addrlist_clear(&al);
568  }
569  }
570  else
571  {
572  for (int i = 0; i < menu->max; i++)
573  {
574  if (query_table[i].tagged)
575  {
576  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
577  if (result_to_addr(&al, query_table[i].data))
578  {
579  mutt_addrlist_copy(&e->env->to, &al, false);
580  mutt_addrlist_clear(&al);
581  }
582  }
583  }
584  }
585  ci_send_message(SEND_NO_FLAGS, e, NULL, Context, NULL);
586  menu->redraw = REDRAW_FULL;
587  break;
588  }
589 
590  case OP_EXIT:
591  done = 1;
592  break;
593  }
594  }
595 
596  /* if we need to return the selected entries */
597  if (retbuf && (done == 2))
598  {
599  bool tagged = false;
600  size_t curpos = 0;
601 
602  memset(buf, 0, buflen);
603 
604  /* check for tagged entries */
605  for (int i = 0; i < menu->max; i++)
606  {
607  if (query_table[i].tagged)
608  {
609  if (curpos == 0)
610  {
611  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
612  if (result_to_addr(&al, query_table[i].data))
613  {
615  tagged = true;
616  mutt_addrlist_write(&al, buf, buflen, false);
617  curpos = mutt_str_strlen(buf);
618  mutt_addrlist_clear(&al);
619  }
620  }
621  else if (curpos + 2 < buflen)
622  {
623  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
624  if (result_to_addr(&al, query_table[i].data))
625  {
627  strcat(buf, ", ");
628  mutt_addrlist_write(&al, buf + curpos + 1, buflen - curpos - 1, false);
629  curpos = mutt_str_strlen(buf);
630  mutt_addrlist_clear(&al);
631  }
632  }
633  }
634  }
635  /* then enter current message */
636  if (!tagged)
637  {
638  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
639  if (result_to_addr(&al, query_table[menu->current].data))
640  {
642  mutt_addrlist_write(&al, buf, buflen, false);
643  mutt_addrlist_clear(&al);
644  }
645  }
646  }
647 
648  query_free(&results);
649  FREE(&query_table);
650  mutt_menu_pop_current(menu);
651  mutt_menu_free(&menu);
652  dialog_pop();
653  mutt_window_free(&dlg);
654 }
The "current" mailbox.
Definition: context.h:37
WHERE bool C_StatusOnTop
Config: Display the status bar at the top.
Definition: globals.h:252
#define REDRAW_FULL
Redraw everything.
Definition: mutt_menu.h:47
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
The envelope/body of an email.
Definition: email.h:37
if(!test_colorize_)
Definition: acutest.h:484
GUI selectable list of items.
Definition: mutt_menu.h:82
Dialog (nested Windows) displayed to the user.
Definition: mutt_window.h:70
Window uses all available vertical space.
Definition: mutt_window.h:35
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1299
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1382
void dialog_pop(void)
Hide a Window from the user.
Definition: mutt_window.c:628
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition: address.c:728
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition: mutt_window.c:605
#define _(a)
Definition: message.h:28
A division of the screen.
Definition: mutt_window.h:88
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:90
An Index Window containing a selection list.
Definition: mutt_window.h:74
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:74
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:87
struct Query * data
Definition: query.c:74
Select from results of external query.
Definition: keymap.h:80
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
struct MuttWindow * win_ibar
Definition: mutt_menu.h:96
const char * title
Title of this menu.
Definition: mutt_menu.h:84
struct Envelope * env
Envelope information.
Definition: email.h:89
struct Query * next
Definition: query.c:65
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
Window has a fixed size.
Definition: mutt_window.h:44
const char * help
Quickref for the current menu.
Definition: mutt_menu.h:85
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
void mutt_alias_create(struct Envelope *cur, struct AddressList *al)
Create a new Alias from an Envelope or an Address.
Definition: alias.c:375
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:93
struct MuttWindow * mutt_window_new(enum MuttWindowOrientation orient, enum MuttWindowSize size, int rows, int cols)
Create a new Window.
Definition: mutt_window.c:56
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition: mutt_window.h:49
bool tagged
Definition: query.c:73
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
bool tagprefix
Definition: mutt_menu.h:93
static const struct Mapping QueryHelp[]
Definition: query.c:77
int ci_send_message(SendFlags flags, struct Email *e_templ, const char *tempfile, struct Context *ctx, struct EmailList *el)
Send an email.
Definition: send.c:1893
int(* tag)(struct Menu *menu, int sel, int act)
Tag some menu items.
Definition: mutt_menu.h:139
static struct Query * run_query(char *s, int quiet)
Run an external program to find Addresses.
Definition: query.c:152
int pagelen
Number of entries per screen.
Definition: mutt_menu.h:92
An entry from an external address-book.
Definition: query.c:59
static int query_search(struct Menu *menu, regex_t *rx, int line)
Search a Address menu item - Implements Menu::search()
Definition: query.c:233
int max
Number of entries in the menu.
Definition: mutt_menu.h:88
void mutt_window_add_child(struct MuttWindow *parent, struct MuttWindow *child)
Add a child to Window.
Definition: mutt_window.c:473
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:89
static int query_tag(struct Menu *menu, int sel, int act)
Tag an entry in the Query Menu - Implements Menu::tag()
Definition: query.c:339
static void query_make_entry(char *buf, size_t buflen, struct Menu *menu, int line)
Format a menu item for the query list - Implements Menu::make_entry()
Definition: query.c:326
#define FREE(x)
Definition: memory.h:40
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
static bool result_to_addr(struct AddressList *al, struct Query *r)
Turn a Query into an AddressList.
Definition: query.c:93
int current
Current entry.
Definition: mutt_menu.h:87
struct MuttWindow * win_index
Definition: mutt_menu.h:95
char * mutt_compile_help(char *buf, size_t buflen, enum MenuType menu, const struct Mapping *items)
Create the text for the help menu.
Definition: help.c:116
Window wants as much space as possible.
Definition: mutt_window.h:45
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
Index Bar containing status info about the Index.
Definition: mutt_window.h:75
enum WindowType type
Window type, e.g. WT_SIDEBAR.
Definition: mutt_window.h:103
int(* search)(struct Menu *menu, regex_t *rx, int line)
Search a menu for a item matching a regex.
Definition: mutt_menu.h:130
void(* make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:120
An entry in a selectable list of Query&#39;s.
Definition: query.c:71
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1138
static const char clear[]
static void query_free(struct Query **query)
Free a Query.
Definition: query.c:127
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_query_complete()

int mutt_query_complete ( char *  buf,
size_t  buflen 
)

Perform auto-complete using an Address Query.

Parameters
bufBuffer for completion
buflenLength of buffer
Return values
0Always

Definition at line 662 of file query.c.

663 {
664  if (!C_QueryCommand)
665  {
666  mutt_error(_("Query command not defined"));
667  return 0;
668  }
669 
670  struct Query *results = run_query(buf, 1);
671  if (results)
672  {
673  /* only one response? */
674  if (!results->next)
675  {
676  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
677  if (result_to_addr(&al, results))
678  {
680  buf[0] = '\0';
681  mutt_addrlist_write(&al, buf, buflen, false);
682  mutt_addrlist_clear(&al);
683  query_free(&results);
685  }
686  return 0;
687  }
688  /* multiple results, choose from query menu */
689  query_menu(buf, buflen, results, true);
690  }
691  return 0;
692 }
static void query_menu(char *buf, size_t buflen, struct Query *results, bool retbuf)
Get the user to enter an Address Query.
Definition: query.c:355
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition: address.c:1299
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1382
#define _(a)
Definition: message.h:28
struct Query * next
Definition: query.c:65
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
static struct Query * run_query(char *s, int quiet)
Run an external program to find Addresses.
Definition: query.c:152
An entry from an external address-book.
Definition: query.c:59
#define mutt_error(...)
Definition: logging.h:84
static bool result_to_addr(struct AddressList *al, struct Query *r)
Turn a Query into an AddressList.
Definition: query.c:93
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
char * C_QueryCommand
Config: External command to query and external address book.
Definition: query.c:53
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1138
static void query_free(struct Query **query)
Free a Query.
Definition: query.c:127
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_query_menu()

void mutt_query_menu ( char *  buf,
size_t  buflen 
)

Show the user the results of a Query.

Parameters
bufBuffer for the query
buflenLength of buffer

Definition at line 699 of file query.c.

700 {
701  if (!C_QueryCommand)
702  {
703  mutt_error(_("Query command not defined"));
704  return;
705  }
706 
707  if (!buf)
708  {
709  char tmp[256] = { 0 };
710 
711  query_menu(tmp, sizeof(tmp), NULL, false);
712  }
713  else
714  {
715  query_menu(buf, buflen, NULL, true);
716  }
717 }
static void query_menu(char *buf, size_t buflen, struct Query *results, bool retbuf)
Get the user to enter an Address Query.
Definition: query.c:355
#define _(a)
Definition: message.h:28
#define mutt_error(...)
Definition: logging.h:84
char * C_QueryCommand
Config: External command to query and external address book.
Definition: query.c:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_QueryCommand

char* C_QueryCommand

Config: External command to query and external address book.

Definition at line 53 of file query.c.

◆ C_QueryFormat

char* C_QueryFormat

Config: printf-like format string for the query menu (address book)

Definition at line 54 of file query.c.

◆ QueryHelp

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

Definition at line 77 of file query.c.