NeoMutt  2019-12-07-60-g0cfa53
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/mutt.h"
#include "address/lib.h"
#include "email/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "query.h"
#include "alias.h"
#include "filter.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::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::menu_make_entry() More...
 
static int query_tag (struct Menu *menu, int sel, int act)
 Tag an entry in the Query Menu - Implements Menu::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 94 of file query.c.

95 {
96  if (!al || !TAILQ_EMPTY(al) || !r)
97  return false;
98 
99  mutt_addrlist_copy(al, &r->addr, false);
100  if (!TAILQ_EMPTY(al))
101  {
102  struct Address *first = TAILQ_FIRST(al);
103  struct Address *second = TAILQ_NEXT(first, entries);
104  if (!second && !first->personal)
105  first->personal = mutt_str_strdup(r->name);
106 
107  mutt_addrlist_to_intl(al, NULL);
108  }
109 
110  return true;
111 }
#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:64
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:63
+ 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 117 of file query.c.

118 {
119  struct Query *query = mutt_mem_calloc(1, sizeof(struct Query));
120  TAILQ_INIT(&query->addr);
121  return query;
122 }
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:60
struct AddressList addr
Definition: query.c:63
+ 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 128 of file query.c.

129 {
130  if (!query)
131  return;
132 
133  struct Query *p = NULL;
134 
135  while (*query)
136  {
137  p = *query;
138  *query = (*query)->next;
139 
141  FREE(&p->name);
142  FREE(&p->other);
143  FREE(&p);
144  }
145 }
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1382
char * name
Definition: query.c:64
struct Query * next
Definition: query.c:66
char * other
Definition: query.c:65
An entry from an external address-book.
Definition: query.c:60
#define FREE(x)
Definition: memory.h:40
struct AddressList addr
Definition: query.c:63
+ 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 153 of file query.c.

154 {
155  FILE *fp = NULL;
156  struct Query *first = NULL;
157  struct Query *cur = NULL;
158  char *buf = NULL;
159  size_t buflen;
160  int dummy = 0;
161  char *msg = NULL;
162  size_t msglen = 0;
163  char *p = NULL;
164  pid_t pid;
165  struct Buffer *cmd = mutt_buffer_pool_get();
166 
168 
169  pid = mutt_create_filter(mutt_b2s(cmd), NULL, &fp, NULL);
170  if (pid < 0)
171  {
172  mutt_debug(LL_DEBUG1, "unable to fork command: %s\n", mutt_b2s(cmd));
174  return 0;
175  }
177 
178  if (!quiet)
179  mutt_message(_("Waiting for response..."));
180 
181  /* The query protocol first reads one NL-terminated line. If an error
182  * occurs, this is assumed to be an error message. Otherwise it's ignored. */
183  msg = mutt_file_read_line(msg, &msglen, fp, &dummy, 0);
184  while ((buf = mutt_file_read_line(buf, &buflen, fp, &dummy, 0)))
185  {
186  p = strtok(buf, "\t\n");
187  if (p)
188  {
189  if (first)
190  {
191  cur->next = query_new();
192  cur = cur->next;
193  }
194  else
195  {
196  first = query_new();
197  cur = first;
198  }
199 
200  mutt_addrlist_parse(&cur->addr, p);
201  p = strtok(NULL, "\t\n");
202  if (p)
203  {
204  cur->name = mutt_str_strdup(p);
205  p = strtok(NULL, "\t\n");
206  if (p)
207  cur->other = mutt_str_strdup(p);
208  }
209  }
210  }
211  FREE(&buf);
212  mutt_file_fclose(&fp);
213  if (mutt_wait_filter(pid))
214  {
215  mutt_debug(LL_DEBUG1, "Error: %s\n", msg);
216  if (!quiet)
217  mutt_error("%s", msg);
218  }
219  else
220  {
221  if (!quiet)
222  mutt_message("%s", msg);
223  }
224  FREE(&msg);
225 
226  return first;
227 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:209
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:64
#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:664
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
struct Query * next
Definition: query.c:66
#define mutt_b2s(buf)
Definition: buffer.h:41
char * other
Definition: query.c:65
An entry from an external address-book.
Definition: query.c:60
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:1423
#define FREE(x)
Definition: memory.h:40
static struct Query * query_new(void)
Create a new query.
Definition: query.c:117
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:220
char * C_QueryCommand
Config: External command to query and external address book.
Definition: query.c:54
struct AddressList addr
Definition: query.c:63
+ 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::menu_search()

Try to match various Address fields.

Definition at line 234 of file query.c.

235 {
236  struct QueryEntry *table = menu->data;
237  struct Query *query = table[line].data;
238 
239  if (query->name && !regexec(rx, query->name, 0, NULL, 0))
240  return 0;
241  if (query->other && !regexec(rx, query->other, 0, NULL, 0))
242  return 0;
243  if (!TAILQ_EMPTY(&query->addr))
244  {
245  struct Address *addr = TAILQ_FIRST(&query->addr);
246  if (addr->personal && !regexec(rx, addr->personal, 0, NULL, 0))
247  {
248  return 0;
249  }
250  if (addr->mailbox && !regexec(rx, addr->mailbox, 0, NULL, 0))
251  {
252  return 0;
253  }
254  }
255 
256  return REG_NOMATCH;
257 }
#define TAILQ_FIRST(head)
Definition: queue.h:716
char * name
Definition: query.c:64
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
struct Query * data
Definition: query.c:75
const char * line
Definition: common.c:36
char * other
Definition: query.c:65
An entry from an external address-book.
Definition: query.c:60
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
struct AddressList addr
Definition: query.c:63
An entry in a selectable list of Query&#39;s.
Definition: query.c:72
+ 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 270 of file query.c.

274 {
275  struct QueryEntry *entry = (struct QueryEntry *) data;
276  struct Query *query = entry->data;
277  char fmt[128];
278  char tmp[256] = { 0 };
279  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
280 
281  switch (op)
282  {
283  case 'a':
284  mutt_addrlist_write(&query->addr, tmp, sizeof(tmp), true);
285  mutt_format_s(buf, buflen, prec, tmp);
286  break;
287  case 'c':
288  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
289  snprintf(buf, buflen, fmt, query->num + 1);
290  break;
291  case 'e':
292  if (!optional)
293  mutt_format_s(buf, buflen, prec, NONULL(query->other));
294  else if (!query->other || !*query->other)
295  optional = false;
296  break;
297  case 'n':
298  mutt_format_s(buf, buflen, prec, NONULL(query->name));
299  break;
300  case 't':
301  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
302  snprintf(buf, buflen, fmt, entry->tagged ? '*' : ' ');
303  break;
304  default:
305  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
306  snprintf(buf, buflen, fmt, op);
307  break;
308  }
309 
310  if (optional)
311  mutt_expando_format(buf, buflen, col, cols, if_str, query_format_str, data,
313  else if (flags & MUTT_FORMAT_OPTIONAL)
314  mutt_expando_format(buf, buflen, col, cols, else_str, query_format_str,
315  data, MUTT_FORMAT_NO_FLAGS);
316 
317  return src;
318 }
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:877
#define NONULL(x)
Definition: string2.h:37
char * name
Definition: query.c:64
#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:270
struct Query * data
Definition: query.c:75
int num
Definition: query.c:62
bool tagged
Definition: query.c:74
char * other
Definition: query.c:65
An entry from an external address-book.
Definition: query.c:60
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:1244
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
struct AddressList addr
Definition: query.c:63
An entry in a selectable list of Query&#39;s.
Definition: query.c:72
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::menu_make_entry()

Definition at line 323 of file query.c.

324 {
325  struct QueryEntry *entry = &((struct QueryEntry *) menu->data)[line];
326 
327  entry->data->num = line;
328  mutt_expando_format(buf, buflen, 0, menu->win_index->state.cols,
330  (unsigned long) entry, MUTT_FORMAT_ARROWCURSOR);
331 }
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:877
#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:55
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:270
struct Query * data
Definition: query.c:75
int num
Definition: query.c:62
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:56
const char * line
Definition: common.c:36
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:91
void * data
Extra data for the current menu.
Definition: mutt_menu.h:86
struct MuttWindow * win_index
Definition: mutt_menu.h:95
An entry in a selectable list of Query&#39;s.
Definition: query.c:72
+ 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::menu_tag()

Definition at line 336 of file query.c.

337 {
338  struct QueryEntry *cur = &((struct QueryEntry *) menu->data)[sel];
339  bool ot = cur->tagged;
340 
341  cur->tagged = ((act >= 0) ? act : !cur->tagged);
342  return cur->tagged - ot;
343 }
bool tagged
Definition: query.c:74
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:72
+ 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 352 of file query.c.

353 {
354  struct Menu *menu = NULL;
355  struct QueryEntry *query_table = NULL;
356  struct Query *queryp = NULL;
357  char title[256];
358 
359  if (!results)
360  {
361  /* Prompt for Query */
362  if ((mutt_get_field(_("Query: "), buf, buflen, 0) == 0) && (buf[0] != '\0'))
363  {
364  results = run_query(buf, 0);
365  if (!results)
366  return;
367  }
368  }
369 
370  snprintf(title, sizeof(title), _("Query '%s'"), buf);
371 
372  struct MuttWindow *dlg =
375  dlg->type = WT_DIALOG;
376  struct MuttWindow *index =
379  index->type = WT_INDEX;
380  struct MuttWindow *ibar = mutt_window_new(
382  ibar->type = WT_INDEX_BAR;
383 
384  if (C_StatusOnTop)
385  {
386  mutt_window_add_child(dlg, ibar);
387  mutt_window_add_child(dlg, index);
388  }
389  else
390  {
391  mutt_window_add_child(dlg, index);
392  mutt_window_add_child(dlg, ibar);
393  }
394 
395  dialog_push(dlg);
396 
397  menu = mutt_menu_new(MENU_QUERY);
398 
399  menu->pagelen = index->state.rows;
400  menu->win_index = index;
401  menu->win_ibar = ibar;
402 
404  menu->menu_search = query_search;
405  menu->menu_tag = query_tag;
406  menu->title = title;
407  char helpstr[1024];
408  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_QUERY, QueryHelp);
410 
411  /* count the number of results */
412  for (queryp = results; queryp; queryp = queryp->next)
413  menu->max++;
414 
415  query_table = mutt_mem_calloc(menu->max, sizeof(struct QueryEntry));
416  menu->data = query_table;
417 
418  queryp = results;
419  for (int i = 0; queryp; queryp = queryp->next, i++)
420  query_table[i].data = queryp;
421 
422  int done = 0;
423  while (done == 0)
424  {
425  const int op = mutt_menu_loop(menu);
426  switch (op)
427  {
428  case OP_QUERY_APPEND:
429  case OP_QUERY:
430  if ((mutt_get_field(_("Query: "), buf, buflen, 0) == 0) && (buf[0] != '\0'))
431  {
432  struct Query *newresults = run_query(buf, 0);
433 
434  menu->redraw = REDRAW_FULL;
435  if (newresults)
436  {
437  snprintf(title, sizeof(title), _("Query '%s'"), buf);
438 
439  if (op == OP_QUERY)
440  {
441  query_free(&results);
442  results = newresults;
443  FREE(&query_table);
444  }
445  else
446  {
447  /* append */
448  for (queryp = results; queryp->next; queryp = queryp->next)
449  ;
450 
451  queryp->next = newresults;
452  }
453 
454  menu->current = 0;
455  mutt_menu_pop_current(menu);
456  mutt_menu_free(&menu);
457  menu = mutt_menu_new(MENU_QUERY);
458 
459  menu->pagelen = index->state.rows;
460  menu->win_index = index;
461  menu->win_ibar = ibar;
462 
464  menu->menu_search = query_search;
465  menu->menu_tag = query_tag;
466  menu->title = title;
467  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_QUERY, QueryHelp);
469 
470  /* count the number of results */
471  for (queryp = results; queryp; queryp = queryp->next)
472  menu->max++;
473 
474  if (op == OP_QUERY)
475  {
476  menu->data = query_table =
477  mutt_mem_calloc(menu->max, sizeof(struct QueryEntry));
478 
479  queryp = results;
480  for (int i = 0; queryp; queryp = queryp->next, i++)
481  query_table[i].data = queryp;
482  }
483  else
484  {
485  bool clear = false;
486 
487  /* append */
488  mutt_mem_realloc(&query_table, menu->max * sizeof(struct QueryEntry));
489 
490  menu->data = query_table;
491 
492  queryp = results;
493  for (int i = 0; queryp; queryp = queryp->next, i++)
494  {
495  /* once we hit new entries, clear/init the tag */
496  if (queryp == newresults)
497  clear = true;
498 
499  query_table[i].data = queryp;
500  if (clear)
501  query_table[i].tagged = false;
502  }
503  }
504  }
505  }
506  break;
507 
508  case OP_CREATE_ALIAS:
509  if (menu->tagprefix)
510  {
511  struct AddressList naddr = TAILQ_HEAD_INITIALIZER(naddr);
512 
513  for (int i = 0; i < menu->max; i++)
514  {
515  if (query_table[i].tagged)
516  {
517  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
518  if (result_to_addr(&al, query_table[i].data))
519  {
520  mutt_addrlist_copy(&naddr, &al, false);
521  mutt_addrlist_clear(&al);
522  }
523  }
524  }
525 
526  mutt_alias_create(NULL, &naddr);
527  mutt_addrlist_clear(&naddr);
528  }
529  else
530  {
531  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
532  if (result_to_addr(&al, query_table[menu->current].data))
533  {
534  mutt_alias_create(NULL, &al);
535  mutt_addrlist_clear(&al);
536  }
537  }
538  break;
539 
540  case OP_GENERIC_SELECT_ENTRY:
541  if (retbuf)
542  {
543  done = 2;
544  break;
545  }
546  /* fallthrough */
547  case OP_MAIL:
548  {
549  struct Email *e = email_new();
550  e->env = mutt_env_new();
551  if (!menu->tagprefix)
552  {
553  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
554  if (result_to_addr(&al, query_table[menu->current].data))
555  {
556  mutt_addrlist_copy(&e->env->to, &al, false);
557  mutt_addrlist_clear(&al);
558  }
559  }
560  else
561  {
562  for (int i = 0; i < menu->max; i++)
563  {
564  if (query_table[i].tagged)
565  {
566  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
567  if (result_to_addr(&al, query_table[i].data))
568  {
569  mutt_addrlist_copy(&e->env->to, &al, false);
570  mutt_addrlist_clear(&al);
571  }
572  }
573  }
574  }
575  ci_send_message(SEND_NO_FLAGS, e, NULL, Context, NULL);
576  menu->redraw = REDRAW_FULL;
577  break;
578  }
579 
580  case OP_EXIT:
581  done = 1;
582  break;
583  }
584  }
585 
586  /* if we need to return the selected entries */
587  if (retbuf && (done == 2))
588  {
589  bool tagged = false;
590  size_t curpos = 0;
591 
592  memset(buf, 0, buflen);
593 
594  /* check for tagged entries */
595  for (int i = 0; i < menu->max; i++)
596  {
597  if (query_table[i].tagged)
598  {
599  if (curpos == 0)
600  {
601  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
602  if (result_to_addr(&al, query_table[i].data))
603  {
605  tagged = true;
606  mutt_addrlist_write(&al, buf, buflen, false);
607  curpos = mutt_str_strlen(buf);
608  mutt_addrlist_clear(&al);
609  }
610  }
611  else if (curpos + 2 < buflen)
612  {
613  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
614  if (result_to_addr(&al, query_table[i].data))
615  {
617  strcat(buf, ", ");
618  mutt_addrlist_write(&al, buf + curpos + 1, buflen - curpos - 1, false);
619  curpos = mutt_str_strlen(buf);
620  mutt_addrlist_clear(&al);
621  }
622  }
623  }
624  }
625  /* then enter current message */
626  if (!tagged)
627  {
628  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
629  if (result_to_addr(&al, query_table[menu->current].data))
630  {
632  mutt_addrlist_write(&al, buf, buflen, false);
633  mutt_addrlist_clear(&al);
634  }
635  }
636  }
637 
638  query_free(&results);
639  FREE(&query_table);
640  mutt_menu_pop_current(menu);
641  mutt_menu_free(&menu);
642  dialog_pop();
643  mutt_window_free(&dlg);
644 }
The "current" mailbox.
Definition: context.h:36
WHERE bool C_StatusOnTop
Config: Display the status bar at the top.
Definition: globals.h:255
#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
GUI selectable list of items.
Definition: mutt_menu.h:82
Dialog (nested Windows) displayed to the user.
Definition: mutt_window.h:68
Window uses all available vertical space.
Definition: mutt_window.h:33
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:623
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:603
#define _(a)
Definition: message.h:28
A division of the screen.
Definition: mutt_window.h:86
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
void(* menu_make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: mutt_menu.h:120
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:92
An Index Window containing a selection list.
Definition: mutt_window.h:72
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:75
#define SEND_NO_FLAGS
No flags are set.
Definition: send.h:87
struct Query * data
Definition: query.c:75
Select from results of external query.
Definition: keymap.h:80
struct MuttWindow * win_ibar
Definition: mutt_menu.h:96
struct Envelope * env
Envelope information.
Definition: email.h:89
struct Query * next
Definition: query.c:66
struct Envelope * mutt_env_new(void)
Create a new Envelope.
Definition: envelope.c:42
Window has a fixed size.
Definition: mutt_window.h:42
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:91
struct MuttWindow * mutt_window_new(enum MuttWindowOrientation orient, enum MuttWindowSize size, int rows, int cols)
Create a new Window.
Definition: mutt_window.c:57
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition: mutt_window.h:47
bool tagged
Definition: query.c:74
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:55
bool tagprefix
Definition: mutt_menu.h:93
static const struct Mapping QueryHelp[]
Definition: query.c:78
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:1880
static struct Query * run_query(char *s, int quiet)
Run an external program to find Addresses.
Definition: query.c:153
int pagelen
Number of entries per screen.
Definition: mutt_menu.h:92
An entry from an external address-book.
Definition: query.c:60
static int query_search(struct Menu *menu, regex_t *rx, int line)
Search a Address menu item - Implements Menu::menu_search()
Definition: query.c:234
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:471
int(* menu_tag)(struct Menu *menu, int sel, int act)
Tag some menu items.
Definition: mutt_menu.h:137
MuttRedrawFlags redraw
When to redraw the screen.
Definition: mutt_menu.h:89
int(* menu_search)(struct Menu *menu, regex_t *rx, int line)
Search a menu for a item matching a regex.
Definition: mutt_menu.h:129
char * title
Title of this menu.
Definition: mutt_menu.h:84
static int query_tag(struct Menu *menu, int sel, int act)
Tag an entry in the Query Menu - Implements Menu::menu_tag()
Definition: query.c:336
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::menu_make_entry()
Definition: query.c:323
#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:94
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:115
Window wants as much space as possible.
Definition: mutt_window.h:43
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
Index Bar containing status info about the Index.
Definition: mutt_window.h:73
enum WindowType type
Window type, e.g. WT_SIDEBAR.
Definition: mutt_window.h:101
An entry in a selectable list of Query&#39;s.
Definition: query.c:72
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
char * help
Quickref for the current menu.
Definition: mutt_menu.h:85
static const char clear[]
static void query_free(struct Query **query)
Free a Query.
Definition: query.c:128
+ 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 652 of file query.c.

653 {
654  if (!C_QueryCommand)
655  {
656  mutt_error(_("Query command not defined"));
657  return 0;
658  }
659 
660  struct Query *results = run_query(buf, 1);
661  if (results)
662  {
663  /* only one response? */
664  if (!results->next)
665  {
666  struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
667  if (result_to_addr(&al, results))
668  {
670  buf[0] = '\0';
671  mutt_addrlist_write(&al, buf, buflen, false);
672  mutt_addrlist_clear(&al);
673  query_free(&results);
675  }
676  return 0;
677  }
678  /* multiple results, choose from query menu */
679  query_menu(buf, buflen, results, true);
680  }
681  return 0;
682 }
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:352
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:66
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:153
An entry from an external address-book.
Definition: query.c:60
#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:94
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:630
char * C_QueryCommand
Config: External command to query and external address book.
Definition: query.c:54
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:128
+ 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 689 of file query.c.

690 {
691  if (!C_QueryCommand)
692  {
693  mutt_error(_("Query command not defined"));
694  return;
695  }
696 
697  if (!buf)
698  {
699  char tmp[256] = { 0 };
700 
701  query_menu(tmp, sizeof(tmp), NULL, false);
702  }
703  else
704  {
705  query_menu(buf, buflen, NULL, true);
706  }
707 }
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:352
#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:54
+ 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 54 of file query.c.

◆ C_QueryFormat

char* C_QueryFormat

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

Definition at line 55 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 78 of file query.c.