NeoMutt  2019-12-07-60-g0cfa53
Teaching an old dog new tricks
DOXYGEN
mutt_window.c
Go to the documentation of this file.
1 
29 #include "config.h"
30 #include <stdarg.h>
31 #include <string.h>
32 #include "mutt/mutt.h"
33 #include "config/lib.h"
34 #include "core/lib.h"
35 #include "mutt_window.h"
36 #include "context.h"
37 #include "globals.h"
38 #include "mutt_curses.h"
39 #include "mutt_menu.h"
40 #include "options.h"
41 #include "pager.h"
42 #include "reflow.h"
43 
44 struct MuttWindow *RootWindow = NULL;
45 struct MuttWindow *MuttDialogWindow = NULL;
46 struct MuttWindow *MuttHelpWindow = NULL;
47 struct MuttWindow *MuttMessageWindow = NULL;
48 
58  enum MuttWindowSize size, int rows, int cols)
59 {
60  struct MuttWindow *win = mutt_mem_calloc(1, sizeof(struct MuttWindow));
61 
62  win->orient = orient;
63  win->size = size;
64  win->req_rows = rows;
65  win->req_cols = cols;
66  win->state.visible = true;
67  TAILQ_INIT(&win->children);
68  return win;
69 }
70 
75 void mutt_window_free(struct MuttWindow **ptr)
76 {
77  if (!ptr || !*ptr)
78  return;
79 
80  struct MuttWindow *win = *ptr;
81 
82  if (win->wdata && win->free_wdata)
83  win->free_wdata(win, &win->wdata); // Custom function to free private data
84 
86 
87  FREE(ptr);
88 }
89 
90 #ifdef USE_SLANG_CURSES
91 
98 static int vw_printw(SLcurses_Window_Type *win, const char *fmt, va_list ap)
99 {
100  char buf[1024];
101 
102  (void) SLvsnprintf(buf, sizeof(buf), (char *) fmt, ap);
103  SLcurses_waddnstr(win, buf, -1);
104  return 0;
105 }
106 #endif
107 
113 void mutt_window_clearline(struct MuttWindow *win, int row)
114 {
115  mutt_window_move(win, row, 0);
117 }
118 
125 {
126  clrtobot();
127 }
128 
136 {
137  if (!win || !stdscr)
138  return;
139 
140  if (win->state.col_offset + win->state.cols == COLS)
141  clrtoeol();
142  else
143  {
144  int row = 0;
145  int col = 0;
146  getyx(stdscr, row, col);
147  int curcol = col;
148  while (curcol < (win->state.col_offset + win->state.cols))
149  {
150  addch(' ');
151  curcol++;
152  }
153  move(row, col);
154  }
155 }
156 
161 {
162  if (!nc->event_data || !nc->global_data)
163  return -1;
164  if (nc->event_type != NT_CONFIG)
165  return 0;
166 
167  struct EventConfig *ec = nc->event_data;
168  struct MuttWindow *root_win = nc->global_data;
169 
170  if (mutt_str_strcmp(ec->name, "help") == 0)
171  {
172  MuttHelpWindow->state.visible = C_Help;
173  goto reflow;
174  }
175 
176  if (mutt_str_strcmp(ec->name, "status_on_top") == 0)
177  {
178  struct MuttWindow *first = TAILQ_FIRST(&root_win->children);
179  if (!first)
180  return -1;
181 
182  if ((C_StatusOnTop && (first->type == WT_HELP_BAR)) ||
183  (!C_StatusOnTop && (first->type != WT_HELP_BAR)))
184  {
185  // Swap the HelpLine and the Dialogs Container
186  struct MuttWindow *next = TAILQ_NEXT(first, entries);
187  if (!next)
188  return -1;
189  TAILQ_REMOVE(&root_win->children, next, entries);
190  TAILQ_INSERT_HEAD(&root_win->children, next, entries);
191  }
192  }
193 
194 reflow:
195  mutt_window_reflow(root_win);
196  return 0;
197 }
198 
203 {
204  if (NeoMutt)
206  MuttDialogWindow = NULL;
207  MuttHelpWindow = NULL;
208  MuttMessageWindow = NULL;
209  mutt_window_free(&RootWindow);
210 }
211 
221 void mutt_window_get_coords(struct MuttWindow *win, int *row, int *col)
222 {
223  int x = 0;
224  int y = 0;
225 
226  getyx(stdscr, y, x);
227  if (col)
228  *col = x - win->state.col_offset;
229  if (row)
230  *row = y - win->state.row_offset;
231 }
232 
239 {
240  if (RootWindow)
241  return;
242 
244  RootWindow->type = WT_ROOT;
247  MuttHelpWindow->type = WT_HELP_BAR;
248  MuttHelpWindow->state.visible = C_Help;
251  MuttDialogWindow->type = WT_ALL_DIALOGS;
254  MuttMessageWindow->type = WT_MESSAGE;
255 
256  if (C_StatusOnTop)
257  {
258  mutt_window_add_child(RootWindow, MuttDialogWindow);
259  mutt_window_add_child(RootWindow, MuttHelpWindow);
260  }
261  else
262  {
263  mutt_window_add_child(RootWindow, MuttHelpWindow);
264  mutt_window_add_child(RootWindow, MuttDialogWindow);
265  }
266 
267  mutt_window_add_child(RootWindow, MuttMessageWindow);
269 }
270 
279 int mutt_window_move(struct MuttWindow *win, int row, int col)
280 {
281  return move(win->state.row_offset + row, win->state.col_offset + col);
282 }
283 
293 int mutt_window_mvaddstr(struct MuttWindow *win, int row, int col, const char *str)
294 {
295 #ifdef USE_SLANG_CURSES
296  return mvaddstr(win->state.row_offset + row, win->state.col_offset + col, (char *) str);
297 #else
298  return mvaddstr(win->state.row_offset + row, win->state.col_offset + col, str);
299 #endif
300 }
301 
312 int mutt_window_mvprintw(struct MuttWindow *win, int row, int col, const char *fmt, ...)
313 {
314  int rc = mutt_window_move(win, row, col);
315  if (rc == ERR)
316  return rc;
317 
318  va_list ap;
319  va_start(ap, fmt);
320  rc = vw_printw(stdscr, fmt, ap);
321  va_end(ap);
322 
323  return rc;
324 }
325 
331 void mutt_window_copy_size(const struct MuttWindow *win_src, struct MuttWindow *win_dst)
332 {
333  if (!win_src || !win_dst)
334  return;
335 
336  win_dst->state.rows = win_src->state.rows;
337  win_dst->state.cols = win_src->state.cols;
338  win_dst->state.row_offset = win_src->state.row_offset;
339  win_dst->state.col_offset = win_src->state.col_offset;
340 }
341 
347 {
348  if (OptNoCurses)
349  return;
350 
351  mutt_debug(LL_DEBUG2, "entering\n");
352  window_reflow(win ? win : RootWindow);
353 
355  /* the pager menu needs this flag set to recalc line_info */
357 }
358 
366 {
367  MuttMessageWindow->req_rows = mw_rows;
368  mutt_window_reflow(MuttMessageWindow->parent);
369 
370  /* We don't also set REDRAW_FLOW because this function only
371  * changes rows and is a temporary adjustment. */
373 }
374 
383 int mutt_window_wrap_cols(int width, short wrap)
384 {
385  if (wrap < 0)
386  return (width > -wrap) ? (width + wrap) : width;
387  if (wrap)
388  return (wrap < width) ? wrap : width;
389  return width;
390 }
391 
398 int mutt_window_addch(int ch)
399 {
400  return addch(ch);
401 }
402 
410 int mutt_window_addnstr(const char *str, int num)
411 {
412  if (!str)
413  return -1;
414 
415 #ifdef USE_SLANG_CURSES
416  return addnstr((char *) str, num);
417 #else
418  return addnstr(str, num);
419 #endif
420 }
421 
428 int mutt_window_addstr(const char *str)
429 {
430  if (!str)
431  return -1;
432 
433 #ifdef USE_SLANG_CURSES
434  return addstr((char *) str);
435 #else
436  return addstr(str);
437 #endif
438 }
439 
445 void mutt_window_move_abs(int row, int col)
446 {
447  move(row, col);
448 }
449 
456 int mutt_window_printf(const char *fmt, ...)
457 {
458  va_list ap;
459  va_start(ap, fmt);
460  int rc = vw_printw(stdscr, fmt, ap);
461  va_end(ap);
462 
463  return rc;
464 }
465 
471 void mutt_window_add_child(struct MuttWindow *parent, struct MuttWindow *child)
472 {
473  if (!parent || !child)
474  return;
475 
476  TAILQ_INSERT_TAIL(&parent->children, child, entries);
477  child->parent = parent;
478 }
479 
484 void mutt_winlist_free(struct MuttWindowList *head)
485 {
486  if (!head)
487  return;
488 
489  struct MuttWindow *np = NULL;
490  struct MuttWindow *tmp = NULL;
491  TAILQ_FOREACH_SAFE(np, head, entries, tmp)
492  {
493  TAILQ_REMOVE(head, np, entries);
495  FREE(&np);
496  }
497 }
498 
504 void mutt_window_set_root(int rows, int cols)
505 {
506  if (!RootWindow)
507  return;
508 
509  bool changed = false;
510 
511  if (RootWindow->state.rows != rows)
512  {
513  RootWindow->state.rows = rows;
514  changed = true;
515  }
516 
517  if (RootWindow->state.cols != cols)
518  {
519  RootWindow->state.cols = cols;
520  changed = true;
521  }
522 
523  if (changed)
524  {
525  mutt_window_reflow(RootWindow);
526  }
527 }
528 
538 {
539  if (!win)
540  return false;
541 
542  for (; win; win = win->parent)
543  {
544  if (!win->state.visible)
545  return false;
546  }
547 
548  return true;
549 }
550 
559 {
560  if (!win)
561  return NULL;
562  if (win->type == WT_DIALOG)
563  return win;
564 
565  return mutt_window_dialog(win->parent);
566 }
567 
576 {
577  if (!root)
578  return NULL;
579  if (root->type == type)
580  return root;
581 
582  struct MuttWindow *np = NULL;
583  struct MuttWindow *match = NULL;
584  TAILQ_FOREACH(np, &root->children, entries)
585  {
586  match = mutt_window_find(np, type);
587  if (match)
588  return match;
589  }
590 
591  return NULL;
592 }
593 
603 void dialog_push(struct MuttWindow *dlg)
604 {
605  if (!dlg || !MuttDialogWindow)
606  return;
607 
608  struct MuttWindow *last = TAILQ_LAST(&MuttDialogWindow->children, MuttWindowList);
609  if (last)
610  last->state.visible = false;
611 
612  TAILQ_INSERT_TAIL(&MuttDialogWindow->children, dlg, entries);
613  dlg->state.visible = true;
614  mutt_window_reflow(MuttDialogWindow);
615 }
616 
623 void dialog_pop(void)
624 {
625  if (!MuttDialogWindow)
626  return;
627 
628  struct MuttWindow *last = TAILQ_LAST(&MuttDialogWindow->children, MuttWindowList);
629  if (!last)
630  return;
631 
632  last->state.visible = false;
633  TAILQ_REMOVE(&MuttDialogWindow->children, last, entries);
634 
635  last = TAILQ_LAST(&MuttDialogWindow->children, MuttWindowList);
636  if (last)
637  {
638  last->state.visible = true;
639  mutt_window_reflow(MuttDialogWindow);
640  }
641 }
void mutt_window_move_abs(int row, int col)
Move the cursor to an absolute screen position.
Definition: mutt_window.c:445
WHERE bool C_StatusOnTop
Config: Display the status bar at the top.
Definition: globals.h:255
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
Define wrapper functions around Curses/Slang.
void mutt_window_get_coords(struct MuttWindow *win, int *row, int *col)
Get the cursor position in the Window.
Definition: mutt_window.c:221
enum MuttWindowOrientation orient
Which direction the Window will expand.
Definition: mutt_window.h:94
#define TAILQ_FIRST(head)
Definition: queue.h:716
Data passed to a notification function.
Definition: observer.h:40
void mutt_window_init(void)
Create the default Windows.
Definition: mutt_window.c:238
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
Window management.
The "currently-open" mailbox.
#define TAILQ_LAST(head, headname)
Definition: queue.h:812
Dialog (nested Windows) displayed to the user.
Definition: mutt_window.h:68
Window for messages/errors and command entry.
Definition: mutt_window.h:71
Window uses all available vertical space.
Definition: mutt_window.h:33
void dialog_pop(void)
Hide a Window from the user.
Definition: mutt_window.c:623
#define REDRAW_FLOW
Used by pager to reflow text.
Definition: mutt_menu.h:49
void mutt_window_free_all(void)
Free all the default Windows.
Definition: mutt_window.c:202
struct MuttWindow * mutt_window_find(struct MuttWindow *root, enum WindowType type)
Find a Window of a given type.
Definition: mutt_window.c:575
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:135
WHERE bool C_Help
Config: Display a help line with common key bindings.
Definition: globals.h:220
void dialog_push(struct MuttWindow *dlg)
Display a Window to the user.
Definition: mutt_window.c:603
WindowType
Type of Window.
Definition: mutt_window.h:64
MuttWindowOrientation
Which way does the Window expand?
Definition: mutt_window.h:31
A config-change event.
Definition: subset.h:68
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:728
Parent of All Windows.
Definition: mutt_window.h:66
WHERE bool OptNoCurses
(pseudo) when sending in batch mode
Definition: options.h:46
A division of the screen.
Definition: mutt_window.h:86
short col_offset
Absolute on-screen column.
Definition: mutt_window.h:58
void window_reflow(struct MuttWindow *win)
Reflow Windows.
Definition: reflow.c:226
Container for Accounts, Notifications.
Definition: neomutt.h:35
bool notify_observer_add(struct Notify *notify, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:154
Convenience wrapper for the config headers.
Hundreds of global variables to back the user variables.
void mutt_window_free(struct MuttWindow **ptr)
Free a Window and its children.
Definition: mutt_window.c:75
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
int mutt_window_addnstr(const char *str, int num)
Write a partial string to a Window.
Definition: mutt_window.c:410
Log at debug level 2.
Definition: logging.h:41
void mutt_window_copy_size(const struct MuttWindow *win_src, struct MuttWindow *win_dst)
Copy the size of one Window to another.
Definition: mutt_window.c:331
void mutt_window_set_root(int rows, int cols)
Set the dimensions of the Root Window.
Definition: mutt_window.c:504
void mutt_window_clearline(struct MuttWindow *win, int row)
Clear a row of a Window.
Definition: mutt_window.c:113
Convenience wrapper for the core headers.
void mutt_winlist_free(struct MuttWindowList *head)
Free a tree of Windows.
Definition: mutt_window.c:484
#define TAILQ_INIT(head)
Definition: queue.h:758
void mutt_window_clrtobot(void)
Clear to the bottom of the Window.
Definition: mutt_window.c:124
void * global_data
Data from notify_observer_add()
Definition: observer.h:45
void(* free_wdata)(struct MuttWindow *win, void **)
Callback function to free private data.
Definition: mutt_window.h:103
Window has a fixed size.
Definition: mutt_window.h:42
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
void mutt_window_reflow_message_rows(int mw_rows)
Resize the Message Window.
Definition: mutt_window.c:365
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:56
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:91
bool visible
Window is visible.
Definition: mutt_window.h:54
bool mutt_window_is_visible(struct MuttWindow *win)
Is the Window visible?
Definition: mutt_window.c:537
struct MuttWindow * mutt_window_new(enum MuttWindowOrientation orient, enum MuttWindowSize size, int rows, int cols)
Create a new Window.
Definition: mutt_window.c:57
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:186
short row_offset
Absolute on-screen row.
Definition: mutt_window.h:57
#define MUTT_WIN_SIZE_UNLIMITED
Use as much space as possible.
Definition: mutt_window.h:47
short rows
Number of rows, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:55
int mutt_dlg_rootwin_observer(struct NotifyCallback *nc)
Listen for config changes affecting the Root Window - Implements observer_t()
Definition: mutt_window.c:160
Help Bar containing list of useful key bindings.
Definition: mutt_window.h:70
GUI present the user with a selectable list.
int mutt_window_wrap_cols(int width, short wrap)
Calculate the wrap column for a given screen width.
Definition: mutt_window.c:383
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:802
enum MuttWindowSize size
Type of Window, e.g. MUTT_WIN_SIZE_FIXED.
Definition: mutt_window.h:95
struct Notify * notify
Notifications handler.
Definition: neomutt.h:37
Container for All Dialogs (nested Windows)
Definition: mutt_window.h:67
int mutt_window_mvaddstr(struct MuttWindow *win, int row, int col, const char *str)
Move the cursor and write a fixed string to a Window.
Definition: mutt_window.c:293
int mutt_window_move(struct MuttWindow *win, int row, int col)
Move the cursor in a Window.
Definition: mutt_window.c:279
void * event_data
Data from notify_send()
Definition: observer.h:44
void mutt_window_add_child(struct MuttWindow *parent, struct MuttWindow *child)
Add a child to Window.
Definition: mutt_window.c:471
Window management.
struct MuttWindow * mutt_window_dialog(struct MuttWindow *win)
Find the parent Dialog of a Window.
Definition: mutt_window.c:558
Config has changed.
Definition: notify_type.h:34
#define TAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:789
GUI display a file/email/help in a viewport with paging.
int mutt_window_printf(const char *fmt,...)
Write a formatted string to a Window.
Definition: mutt_window.c:456
int mutt_window_addch(int ch)
Write one character to a Window.
Definition: mutt_window.c:398
void mutt_window_reflow(struct MuttWindow *win)
Resize a Window and its children.
Definition: mutt_window.c:346
struct MuttWindow * parent
Parent Window.
Definition: mutt_window.h:98
#define FREE(x)
Definition: memory.h:40
MuttWindowSize
Control the allocation of Window space.
Definition: mutt_window.h:40
struct MuttWindowList children
Children Windows.
Definition: mutt_window.h:99
short req_rows
Number of rows required.
Definition: mutt_window.h:88
int mutt_window_mvprintw(struct MuttWindow *win, int row, int col, const char *fmt,...)
Move the cursor and write a formatted string to a Window.
Definition: mutt_window.c:312
int mutt_window_addstr(const char *str)
Write a string to a Window.
Definition: mutt_window.c:428
#define TAILQ_NEXT(elm, field)
Definition: queue.h:825
Handling of global boolean variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Window wants as much space as possible.
Definition: mutt_window.h:43
void * wdata
Private data.
Definition: mutt_window.h:102
enum WindowType type
Window type, e.g. WT_SIDEBAR.
Definition: mutt_window.h:101
const char * name
Name of config item that changed.
Definition: subset.h:71
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
short req_cols
Number of columns required.
Definition: mutt_window.h:89