NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
window.c
Go to the documentation of this file.
1 
70 #include "config.h"
71 #include <stdbool.h>
72 #include <stdint.h>
73 #include <stdio.h>
74 #include <string.h>
75 #include "private.h"
76 #include "mutt/lib.h"
77 #include "config/lib.h"
78 #include "email/lib.h"
79 #include "core/lib.h"
80 #include "gui/lib.h"
81 #include "index/lib.h"
82 #include "format_flags.h"
83 #include "muttlib.h"
84 
89 {
90  struct SbEntry *entry;
92 };
93 
100 static int imap_is_prefix(const char *folder, const char *mbox)
101 {
102  int plen = 0;
103 
104  struct Url *url_m = url_parse(mbox);
105  struct Url *url_f = url_parse(folder);
106  if (!url_m || !url_f)
107  goto done;
108 
109  if (!mutt_istr_equal(url_m->host, url_f->host))
110  goto done;
111 
112  if (url_m->user && url_f->user && !mutt_istr_equal(url_m->user, url_f->user))
113  goto done;
114 
115  size_t mlen = mutt_str_len(url_m->path);
116  size_t flen = mutt_str_len(url_f->path);
117  if (flen > mlen)
118  goto done;
119 
120  if (!mutt_strn_equal(url_m->path, url_f->path, flen))
121  goto done;
122 
123  plen = strlen(mbox) - mlen + flen;
124 
125 done:
126  url_free(&url_m);
127  url_free(&url_f);
128 
129  return plen;
130 }
131 
139 static const char *abbrev_folder(const char *mbox, const char *folder, enum MailboxType type)
140 {
141  if (!mbox || !folder)
142  return NULL;
143 
144  if (type == MUTT_IMAP)
145  {
146  int prefix = imap_is_prefix(folder, mbox);
147  if (prefix == 0)
148  return NULL;
149  return mbox + prefix;
150  }
151 
152  const char *const c_sidebar_delim_chars =
153  cs_subset_string(NeoMutt->sub, "sidebar_delim_chars");
154  if (!c_sidebar_delim_chars)
155  return NULL;
156 
157  size_t flen = mutt_str_len(folder);
158  if (flen == 0)
159  return NULL;
160  if (strchr(c_sidebar_delim_chars, folder[flen - 1])) // folder ends with a delimiter
161  flen--;
162 
163  size_t mlen = mutt_str_len(mbox);
164  if (mlen < flen)
165  return NULL;
166 
167  if (!mutt_strn_equal(folder, mbox, flen))
168  return NULL;
169 
170  // After the match, check that mbox has a delimiter
171  if (!strchr(c_sidebar_delim_chars, mbox[flen]))
172  return NULL;
173 
174  if (mlen > flen)
175  {
176  return mbox + flen + 1;
177  }
178 
179  // mbox and folder are equal, use the chunk after the last delimiter
180  while (mlen--)
181  {
182  if (strchr(c_sidebar_delim_chars, mbox[mlen]))
183  {
184  return mbox + mlen + 1;
185  }
186  }
187 
188  return NULL;
189 }
190 
203 static const char *abbrev_url(const char *mbox, enum MailboxType type)
204 {
205  /* This is large enough to skip `notmuch://`,
206  * but not so large that it will go past the host part. */
207  const int scheme_len = 10;
208 
209  size_t len = mutt_str_len(mbox);
210  if ((len < scheme_len) || ((type != MUTT_NNTP) && (type != MUTT_IMAP) &&
211  (type != MUTT_NOTMUCH) && (type != MUTT_POP)))
212  {
213  return mbox;
214  }
215 
216  const char split = (type == MUTT_NOTMUCH) ? '?' : '/';
217 
218  // Skip over the scheme, e.g. `imaps://`, `notmuch://`
219  const char *last = strchr(mbox + scheme_len, split);
220  if (last)
221  mbox = last + 1;
222  return mbox;
223 }
224 
232 static size_t add_indent(char *buf, size_t buflen, const struct SbEntry *sbe)
233 {
234  size_t res = 0;
235  const char *const c_sidebar_indent_string =
236  cs_subset_string(NeoMutt->sub, "sidebar_indent_string");
237  for (int i = 0; i < sbe->depth; i++)
238  {
239  res += mutt_str_copy(buf + res, c_sidebar_indent_string, buflen - res);
240  }
241  return res;
242 }
243 
251 static enum ColorId calc_color(const struct Mailbox *m, bool current, bool highlight)
252 {
253  if (current)
254  {
257  return MT_COLOR_INDICATOR;
258  }
259 
260  if (highlight)
262 
263  if (m->has_new)
264  return MT_COLOR_SIDEBAR_NEW;
265  if (m->msg_unread > 0)
267  if (m->msg_flagged > 0)
269 
270  const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
272  mutt_str_equal(mailbox_path(m), c_spool_file))
273  {
275  }
276 
279 
280  return MT_COLOR_NORMAL;
281 }
282 
289 static int calc_path_depth(const char *mbox, const char *delims, const char **last_part)
290 {
291  if (!mbox || !delims || !last_part)
292  return 0;
293 
294  int depth = 0;
295  const char *match = NULL;
296  while ((match = strpbrk(mbox, delims)))
297  {
298  depth++;
299  mbox = match + 1;
300  }
301 
302  *last_part = mbox;
303  return depth;
304 }
305 
325 static const char *sidebar_format_str(char *buf, size_t buflen, size_t col, int cols,
326  char op, const char *src, const char *prec,
327  const char *if_str, const char *else_str,
328  intptr_t data, MuttFormatFlags flags)
329 {
330  struct SidebarFormatData *sfdata = (struct SidebarFormatData *) data;
331  struct SbEntry *sbe = sfdata->entry;
332  struct IndexSharedData *shared = sfdata->shared;
333  char fmt[256];
334 
335  if (!sbe || !shared || !buf)
336  return src;
337 
338  buf[0] = '\0'; /* Just in case there's nothing to do */
339 
340  struct Mailbox *m = sbe->mailbox;
341  if (!m)
342  return src;
343 
344  struct Mailbox *m_cur = shared->mailbox;
345 
346  bool c = m_cur && mutt_str_equal(m_cur->realpath, m->realpath);
347 
348  bool optional = (flags & MUTT_FORMAT_OPTIONAL);
349 
350  switch (op)
351  {
352  case 'B':
353  case 'D':
354  {
355  char indented[256] = { 0 };
356  size_t ilen = sizeof(indented);
357  size_t off = add_indent(indented, ilen, sbe);
358  snprintf(indented + off, ilen - off, "%s",
359  ((op == 'D') && sbe->mailbox->name) ? sbe->mailbox->name : sbe->box);
360  mutt_format_s(buf, buflen, prec, indented);
361  break;
362  }
363 
364  case 'd':
365  if (!optional)
366  {
367  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
368  snprintf(buf, buflen, fmt, c ? m_cur->msg_deleted : 0);
369  }
370  else if ((c && (m_cur->msg_deleted == 0)) || !c)
371  optional = false;
372  break;
373 
374  case 'F':
375  if (!optional)
376  {
377  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
378  snprintf(buf, buflen, fmt, m->msg_flagged);
379  }
380  else if (m->msg_flagged == 0)
381  optional = false;
382  break;
383 
384  case 'L':
385  if (!optional)
386  {
387  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
388  snprintf(buf, buflen, fmt, c ? m_cur->vcount : m->msg_count);
389  }
390  else if ((c && (m_cur->vcount == m->msg_count)) || !c)
391  optional = false;
392  break;
393 
394  case 'N':
395  if (!optional)
396  {
397  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
398  snprintf(buf, buflen, fmt, m->msg_unread);
399  }
400  else if (m->msg_unread == 0)
401  optional = false;
402  break;
403 
404  case 'n':
405  if (!optional)
406  {
407  snprintf(fmt, sizeof(fmt), "%%%sc", prec);
408  snprintf(buf, buflen, fmt, m->has_new ? 'N' : ' ');
409  }
410  else if (m->has_new == false)
411  optional = false;
412  break;
413 
414  case 'o':
415  if (!optional)
416  {
417  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
418  snprintf(buf, buflen, fmt, m->msg_unread - m->msg_new);
419  }
420  else if ((c && (m_cur->msg_unread - m_cur->msg_new) == 0) || !c)
421  optional = false;
422  break;
423 
424  case 'r':
425  if (!optional)
426  {
427  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
428  snprintf(buf, buflen, fmt, m->msg_count - m->msg_unread);
429  }
430  else if ((c && (m_cur->msg_count - m_cur->msg_unread) == 0) || !c)
431  optional = false;
432  break;
433 
434  case 'S':
435  if (!optional)
436  {
437  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
438  snprintf(buf, buflen, fmt, m->msg_count);
439  }
440  else if (m->msg_count == 0)
441  optional = false;
442  break;
443 
444  case 't':
445  if (!optional)
446  {
447  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
448  snprintf(buf, buflen, fmt, c ? m_cur->msg_tagged : 0);
449  }
450  else if ((c && (m_cur->msg_tagged == 0)) || !c)
451  optional = false;
452  break;
453 
454  case 'Z':
455  if (!optional)
456  {
457  snprintf(fmt, sizeof(fmt), "%%%sd", prec);
458  snprintf(buf, buflen, fmt, m->msg_new);
459  }
460  else if ((c && (m_cur->msg_new) == 0) || !c)
461  optional = false;
462  break;
463 
464  case '!':
465  if (m->msg_flagged == 0)
466  mutt_format_s(buf, buflen, prec, "");
467  else if (m->msg_flagged == 1)
468  mutt_format_s(buf, buflen, prec, "!");
469  else if (m->msg_flagged == 2)
470  mutt_format_s(buf, buflen, prec, "!!");
471  else
472  {
473  snprintf(fmt, sizeof(fmt), "%d!", m->msg_flagged);
474  mutt_format_s(buf, buflen, prec, fmt);
475  }
476  break;
477  }
478 
479  if (optional)
480  {
481  mutt_expando_format(buf, buflen, col, cols, if_str, sidebar_format_str, data, flags);
482  }
483  else if (flags & MUTT_FORMAT_OPTIONAL)
484  {
485  mutt_expando_format(buf, buflen, col, cols, else_str, sidebar_format_str, data, flags);
486  }
487 
488  /* We return the format string, unchanged */
489  return src;
490 }
491 
504 static void make_sidebar_entry(char *buf, size_t buflen, int width,
505  struct SbEntry *sbe, struct IndexSharedData *shared)
506 {
507  struct SidebarFormatData data = { sbe, shared };
508 
509  const char *const c_sidebar_format =
510  cs_subset_string(NeoMutt->sub, "sidebar_format");
511  mutt_expando_format(buf, buflen, 0, width, NONULL(c_sidebar_format),
512  sidebar_format_str, (intptr_t) &data, MUTT_FORMAT_NO_FLAGS);
513 
514  /* Force string to be exactly the right width */
515  int w = mutt_strwidth(buf);
516  int s = mutt_str_len(buf);
517  width = MIN(buflen, width);
518  if (w < width)
519  {
520  /* Pad with spaces */
521  memset(buf + s, ' ', width - w);
522  buf[s + width - w] = '\0';
523  }
524  else if (w > width)
525  {
526  /* Truncate to fit */
527  size_t len = mutt_wstr_trunc(buf, buflen, width, NULL);
528  buf[len] = '\0';
529  }
530 }
531 
544 {
545  /* Aliases for readability */
546  const bool c_sidebar_new_mail_only =
547  cs_subset_bool(NeoMutt->sub, "sidebar_new_mail_only");
548  const bool c_sidebar_non_empty_mailbox_only =
549  cs_subset_bool(NeoMutt->sub, "sidebar_non_empty_mailbox_only");
550  struct SbEntry *sbe = NULL;
551 
552  struct IndexSharedData *shared = wdata->shared;
553  struct SbEntry **sbep = NULL;
554  ARRAY_FOREACH(sbep, &wdata->entries)
555  {
556  int i = ARRAY_FOREACH_IDX;
557  sbe = *sbep;
558 
559  sbe->is_hidden = false;
560 
561  if (sbe->mailbox->flags & MB_HIDDEN)
562  {
563  sbe->is_hidden = true;
564  continue;
565  }
566 
567  if (shared->mailbox &&
569  {
570  /* Spool directories are always visible */
571  continue;
572  }
573 
576  {
577  /* Explicitly asked to be visible */
578  continue;
579  }
580 
581  if (c_sidebar_non_empty_mailbox_only && (i != wdata->opn_index) &&
582  (sbe->mailbox->msg_count == 0))
583  {
584  sbe->is_hidden = true;
585  }
586 
587  if (c_sidebar_new_mail_only && (i != wdata->opn_index) &&
588  (sbe->mailbox->msg_unread == 0) && (sbe->mailbox->msg_flagged == 0) &&
589  !sbe->mailbox->has_new)
590  {
591  sbe->is_hidden = true;
592  }
593  }
594 }
595 
609 static bool prepare_sidebar(struct SidebarWindowData *wdata, int page_size)
610 {
611  if (ARRAY_EMPTY(&wdata->entries) || (page_size <= 0))
612  return false;
613 
614  struct SbEntry **sbep = NULL;
615  const bool c_sidebar_new_mail_only =
616  cs_subset_bool(NeoMutt->sub, "sidebar_new_mail_only");
617  const bool c_sidebar_non_empty_mailbox_only =
618  cs_subset_bool(NeoMutt->sub, "sidebar_non_empty_mailbox_only");
619 
620  sbep = (wdata->opn_index >= 0) ? ARRAY_GET(&wdata->entries, wdata->opn_index) : NULL;
621  const struct SbEntry *opn_entry = sbep ? *sbep : NULL;
622  sbep = (wdata->hil_index >= 0) ? ARRAY_GET(&wdata->entries, wdata->hil_index) : NULL;
623  const struct SbEntry *hil_entry = sbep ? *sbep : NULL;
624 
626  const short c_sidebar_sort_method =
627  cs_subset_sort(NeoMutt->sub, "sidebar_sort_method");
628  sb_sort_entries(wdata, c_sidebar_sort_method);
629 
630  if (opn_entry || hil_entry)
631  {
632  ARRAY_FOREACH(sbep, &wdata->entries)
633  {
634  if ((opn_entry == *sbep) && ((*sbep)->mailbox->flags != MB_HIDDEN))
635  wdata->opn_index = ARRAY_FOREACH_IDX;
636  if ((hil_entry == *sbep) && ((*sbep)->mailbox->flags != MB_HIDDEN))
637  wdata->hil_index = ARRAY_FOREACH_IDX;
638  }
639  }
640 
641  if ((wdata->hil_index < 0) || (hil_entry && hil_entry->is_hidden) ||
642  (c_sidebar_sort_method != wdata->previous_sort))
643  {
644  if (wdata->opn_index >= 0)
645  wdata->hil_index = wdata->opn_index;
646  else
647  {
648  wdata->hil_index = 0;
649  /* Note is_hidden will only be set when `$sidebar_new_mail_only` */
650  if ((*ARRAY_GET(&wdata->entries, 0))->is_hidden && !select_next(wdata))
651  wdata->hil_index = -1;
652  }
653  }
654 
655  /* Set the Top and Bottom to frame the wdata->hil_index in groups of page_size */
656 
657  /* If `$sidebar_new_mail_only` or `$sidebar_non_empty_mailbox_only` is set,
658  * some entries may be hidden so we need to scan for the framing interval */
659  if (c_sidebar_new_mail_only || c_sidebar_non_empty_mailbox_only)
660  {
661  wdata->top_index = -1;
662  wdata->bot_index = -1;
663  while (wdata->bot_index < wdata->hil_index)
664  {
665  wdata->top_index = wdata->bot_index + 1;
666  int page_entries = 0;
667  while (page_entries < page_size)
668  {
669  wdata->bot_index++;
670  if (wdata->bot_index >= ARRAY_SIZE(&wdata->entries))
671  break;
672  if (!(*ARRAY_GET(&wdata->entries, wdata->bot_index))->is_hidden)
673  page_entries++;
674  }
675  }
676  }
677  /* Otherwise we can just calculate the interval */
678  else
679  {
680  wdata->top_index = (wdata->hil_index / page_size) * page_size;
681  wdata->bot_index = wdata->top_index + page_size - 1;
682  }
683 
684  if (wdata->bot_index > (ARRAY_SIZE(&wdata->entries) - 1))
685  wdata->bot_index = ARRAY_SIZE(&wdata->entries) - 1;
686 
687  wdata->previous_sort = c_sidebar_sort_method;
688 
689  return (wdata->hil_index >= 0);
690 }
691 
695 int sb_recalc(struct MuttWindow *win)
696 {
697  if (!mutt_window_is_visible(win))
698  return 0;
699 
700  struct SidebarWindowData *wdata = sb_wdata_get(win);
701  struct IndexSharedData *shared = wdata->shared;
702 
703  if (ARRAY_EMPTY(&wdata->entries))
704  {
705  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
707  struct MailboxNode *np = NULL;
708  STAILQ_FOREACH(np, &ml, entries)
709  {
710  if (!(np->mailbox->flags & MB_HIDDEN))
711  sb_add_mailbox(wdata, np->mailbox);
712  }
714  }
715 
716  if (!prepare_sidebar(wdata, win->state.rows))
717  {
718  win->actions |= WA_REPAINT;
719  return 0;
720  }
721 
722  int num_rows = win->state.rows;
723  int num_cols = win->state.cols;
724 
725  if (ARRAY_EMPTY(&wdata->entries) || (num_rows <= 0))
726  return 0;
727 
728  if (wdata->top_index < 0)
729  return 0;
730 
731  int width = num_cols - wdata->divider_width;
732  int row = 0;
733  struct Mailbox *m_cur = shared->mailbox;
734  struct SbEntry **sbep = NULL;
735  ARRAY_FOREACH_FROM(sbep, &wdata->entries, wdata->top_index)
736  {
737  if (row >= num_rows)
738  break;
739 
740  if ((*sbep)->is_hidden)
741  continue;
742 
743  struct SbEntry *entry = (*sbep);
744  struct Mailbox *m = entry->mailbox;
745 
746  const int entryidx = ARRAY_FOREACH_IDX;
747  entry->color =
748  calc_color(m, (entryidx == wdata->opn_index), (entryidx == wdata->hil_index));
749 
750  if (m_cur && (m_cur->realpath[0] != '\0') &&
751  mutt_str_equal(m->realpath, m_cur->realpath))
752  {
753  m->msg_unread = m_cur->msg_unread;
754  m->msg_count = m_cur->msg_count;
755  m->msg_flagged = m_cur->msg_flagged;
756  }
757 
758  const char *path = mailbox_path(m);
759 
760  const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
761  // Try to abbreviate the full path
762  const char *abbr = abbrev_folder(path, c_folder, m->type);
763  if (!abbr)
764  abbr = abbrev_url(path, m->type);
765  const char *short_path = abbr ? abbr : path;
766 
767  /* Compute the depth */
768  const char *last_part = abbr;
769  const char *const c_sidebar_delim_chars =
770  cs_subset_string(NeoMutt->sub, "sidebar_delim_chars");
771  entry->depth = calc_path_depth(abbr, c_sidebar_delim_chars, &last_part);
772 
773  const bool short_path_is_abbr = (short_path == abbr);
774  const bool c_sidebar_short_path =
775  cs_subset_bool(NeoMutt->sub, "sidebar_short_path");
776  if (c_sidebar_short_path)
777  {
778  short_path = last_part;
779  }
780 
781  // Don't indent if we were unable to create an abbreviation.
782  // Otherwise, the full path will be indent, and it looks unusual.
783  const bool c_sidebar_folder_indent =
784  cs_subset_bool(NeoMutt->sub, "sidebar_folder_indent");
785  if (c_sidebar_folder_indent && short_path_is_abbr)
786  {
787  const short c_sidebar_component_depth =
788  cs_subset_number(NeoMutt->sub, "sidebar_component_depth");
789  if (c_sidebar_component_depth > 0)
790  entry->depth -= c_sidebar_component_depth;
791  }
792  else if (!c_sidebar_folder_indent)
793  entry->depth = 0;
794 
795  mutt_str_copy(entry->box, short_path, sizeof(entry->box));
796  make_sidebar_entry(entry->display, sizeof(entry->display), width, entry, shared);
797  row++;
798  }
799 
800  win->actions |= WA_REPAINT;
801  mutt_debug(LL_DEBUG5, "recalc done, request WA_REPAINT\n");
802  return 0;
803 }
804 
821 static int draw_divider(struct SidebarWindowData *wdata, struct MuttWindow *win,
822  int num_rows, int num_cols)
823 {
824  if ((num_rows < 1) || (num_cols < 1) || (wdata->divider_width > num_cols))
825  return 0;
826 
827  const int width = wdata->divider_width;
828  const char *const c_sidebar_divider_char =
829  cs_subset_string(NeoMutt->sub, "sidebar_divider_char");
830 
832 
833  const bool c_sidebar_on_right =
834  cs_subset_bool(NeoMutt->sub, "sidebar_on_right");
835  const int col = c_sidebar_on_right ? 0 : (num_cols - width);
836 
837  for (int i = 0; i < num_rows; i++)
838  {
839  mutt_window_move(win, col, i);
840 
841  switch (wdata->divider_type)
842  {
843  case SB_DIV_USER:
844  mutt_window_addstr(win, NONULL(c_sidebar_divider_char));
845  break;
846  case SB_DIV_ASCII:
847  mutt_window_addch(win, '|');
848  break;
849  case SB_DIV_UTF8:
850  mutt_window_addch(win, ACS_VLINE);
851  break;
852  }
853  }
854 
856  return width;
857 }
858 
869 static void fill_empty_space(struct MuttWindow *win, int first_row,
870  int num_rows, int div_width, int num_cols)
871 {
872  /* Fill the remaining rows with blank space */
874 
875  const bool c_sidebar_on_right =
876  cs_subset_bool(NeoMutt->sub, "sidebar_on_right");
877  if (!c_sidebar_on_right)
878  div_width = 0;
879  for (int r = 0; r < num_rows; r++)
880  {
881  mutt_window_move(win, div_width, first_row + r);
882 
883  for (int i = 0; i < num_cols; i++)
884  mutt_window_addch(win, ' ');
885  }
886 }
887 
891 int sb_repaint(struct MuttWindow *win)
892 {
893  if (!mutt_window_is_visible(win))
894  return 0;
895 
896  struct SidebarWindowData *wdata = sb_wdata_get(win);
897  const bool c_sidebar_on_right =
898  cs_subset_bool(NeoMutt->sub, "sidebar_on_right");
899 
900  int row = 0;
901  int num_rows = win->state.rows;
902  int num_cols = win->state.cols;
903 
904  if (wdata->top_index >= 0)
905  {
906  int col = 0;
907  if (c_sidebar_on_right)
908  col = wdata->divider_width;
909 
910  struct SbEntry **sbep = NULL;
911  ARRAY_FOREACH_FROM(sbep, &wdata->entries, wdata->top_index)
912  {
913  if (row >= num_rows)
914  break;
915 
916  if ((*sbep)->is_hidden)
917  continue;
918 
919  struct SbEntry *entry = (*sbep);
920  mutt_window_move(win, col, row);
922  mutt_window_printf(win, "%s", entry->display);
923  mutt_refresh();
924  row++;
925  }
926  }
927 
928  fill_empty_space(win, row, num_rows - row, wdata->divider_width,
929  num_cols - wdata->divider_width);
930  draw_divider(wdata, win, num_rows, num_cols);
931 
932  mutt_debug(LL_DEBUG5, "repaint done\n");
933  return 0;
934 }
int sb_repaint(struct MuttWindow *win)
Repaint the Sidebar display - Implements MuttWindow::repaint() -.
Definition: window.c:891
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
Convenience wrapper for the gui headers.
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
char display[256]
Formatted string to display.
Definition: private.h:42
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:780
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
#define NONULL(x)
Definition: string2.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:91
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Data passed to sidebar_format_str()
Definition: window.c:88
int opn_index
Current (open) mailbox.
Definition: private.h:68
enum DivType divider_type
Type of divider to use, e.g. SB_DIV_ASCII.
Definition: private.h:73
#define MIN(a, b)
Definition: memory.h:31
#define WA_REPAINT
Redraw the contents of the Window.
Definition: mutt_window.h:111
int top_index
First mailbox visible in sidebar.
Definition: private.h:67
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
int msg_unread
Number of unread messages.
Definition: mailbox.h:92
static const char * sidebar_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 sidebar - Implements format_t -Expando Description %! &#39;n!&#39; Flagged messages ...
Definition: window.c:325
&#39;NNTP&#39; (Usenet) Mailbox type
Definition: mailbox.h:52
Structs that make up an email.
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:93
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:68
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:141
void mutt_curses_set_color(enum ColorId color)
Set the current colour for text.
Definition: mutt_curses.c:56
Mailbox with no new or flagged messages.
Definition: color.h:70
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:206
Match any Mailbox type.
Definition: mailbox.h:45
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:164
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:105
Line dividing sidebar from the index/pager.
Definition: color.h:65
struct SbEntry * entry
Info about a folder.
Definition: window.c:90
Data shared between Index, Pager and Sidebar.
Definition: shared_data.h:36
Sidebar private Window data -.
Definition: private.h:62
enum ColorId color
Colour to use.
Definition: private.h:46
Select cursor.
Definition: color.h:67
Info about folders in the sidebar.
Definition: private.h:39
int hil_index
Highlighted mailbox.
Definition: private.h:69
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
bool is_hidden
Don&#39;t show, e.g. $sidebar_new_mail_only.
Definition: private.h:45
Flags to control mutt_expando_format()
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
Container for Accounts, Notifications.
Definition: neomutt.h:36
short previous_sort
Old $sidebar_sort_method
Definition: private.h:72
Mailbox with new mail.
Definition: color.h:69
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
Current open mailbox.
Definition: color.h:68
int vcount
The number of virtual messages.
Definition: mailbox.h:102
Convenience wrapper for the config headers.
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:310
Some miscellaneous functions.
bool has_new
Mailbox has new mail.
Definition: mailbox.h:88
WindowActionFlags actions
Actions to be performed, e.g. WA_RECALC.
Definition: mutt_window.h:132
struct Mailbox * mailbox
Mailbox this represents.
Definition: private.h:44
char * name
A short name for the Mailbox.
Definition: mailbox.h:85
int mutt_window_addstr(struct MuttWindow *win, const char *str)
Write a string to a Window.
Definition: mutt_window.c:434
Convenience wrapper for the core headers.
ColorId
List of all colored objects.
Definition: color.h:39
struct ListNode * mutt_list_find(const struct ListHead *h, const char *data)
Find a string in a List.
Definition: list.c:102
Plain text.
Definition: color.h:58
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:115
#define MB_HIDDEN
Definition: mailbox.h:38
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
char box[256]
Mailbox path (possibly abbreviated)
Definition: private.h:41
bool mutt_window_is_visible(struct MuttWindow *win)
Is the Window visible?
Definition: mutt_window.c:529
A mailbox.
Definition: mailbox.h:81
int mutt_strwidth(const char *s)
Measure a string&#39;s width in screen cells.
Definition: curs_lib.c:983
char * user
Username.
Definition: url.h:71
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:61
int mutt_window_printf(struct MuttWindow *win, const char *fmt,...)
Write a formatted string to a Window.
Definition: mutt_window.c:453
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:70
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
Definition: curs_lib.c:933
Selected item in list.
Definition: color.h:54
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
char * host
Host.
Definition: url.h:73
int msg_tagged
How many messages are tagged?
Definition: mailbox.h:97
int sb_recalc(struct MuttWindow *win)
Recalculate the Sidebar display - Implements MuttWindow::recalc() -.
Definition: window.c:695
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int mutt_color(enum ColorId id)
Return the color of an object.
Definition: color.c:1427
char * path
Path.
Definition: url.h:75
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
#define ARRAY_FOREACH_FROM(elem, head, from)
Iterate from an index to the end.
Definition: array.h:217
short divider_width
Width of the divider in screen columns.
Definition: private.h:74
uint8_t flags
e.g. MB_NORMAL
Definition: mailbox.h:134
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:664
struct IndexSharedData * shared
Shared Index Data.
Definition: window.c:91
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
void mutt_format_s(char *buf, size_t buflen, const char *prec, const char *s)
Format a simple string.
Definition: curs_lib.c:867
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
int msg_new
Number of new messages.
Definition: mailbox.h:95
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
Definition: string.c:593
int depth
Indentation depth.
Definition: private.h:43
Mailbox with unread mail.
Definition: color.h:72
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define MUTT_FORMAT_OPTIONAL
Allow optional field processing.
Definition: format_flags.h:33
List of Mailboxes.
Definition: mailbox.h:156
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Mailbox * mailbox
Current Mailbox.
Definition: shared_data.h:41
Log at debug level 5.
Definition: logging.h:44
Convenience wrapper for the library headers.
int bot_index
Last mailbox visible in sidebar.
Definition: private.h:70
GUI manage the main index (list of emails)
struct IndexSharedData * shared
Definition: private.h:64
void * wdata
Private data.
Definition: mutt_window.h:145
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
char * src
Raw URL string.
Definition: url.h:77
Mailbox with flagged messages.
Definition: color.h:66
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:83
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
Definition: mutt_window.c:402
$spool_file (Spool mailbox)
Definition: color.h:71
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:158
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234