1 #ifndef EL__BFU_DIALOG_H
2 #define EL__BFU_DIALOG_H
3 
4 #include "bfu/style.h"
5 #include "bfu/widget.h"
6 #include "main/timer.h" /* timer_id_T */
7 #include "terminal/terminal.h"
8 #include "terminal/window.h" /* dialog_data->win->term is so common that... */
9 #include "util/memlist.h"
10 
11 
12 struct dialog_data;
13 struct term_event;
14 
15 struct dialog_layout {
16 	/* Whether to adjust the dialog width to the maximal width. If not set
17 	 * only use required width. */
18 	unsigned int maximize_width:1;
19 	/* Whether to leave one blank line at the top of the dialog. */
20 	unsigned int padding_top:1;
21 	/* Whether to adjust width to fit datalen of _first_ widget. */
22 	unsigned int fit_datalen:1;
23 	/* Whether to float grouped widgets on one line. */
24 	unsigned int float_groups:1;
25 	/* Whether to draw all the fancy frames and backgrounds. */
26 	unsigned int only_widgets:1;
27 };
28 
29 enum dlg_refresh_code {
30 	/* The dialog should be redrawn and refreshed again */
31 	REFRESH_DIALOG,
32 	/* The dialog should be canceled */
33 	REFRESH_CANCEL,
34 	/* The dialog should not be redrawn but refreshed again */
35 	REFRESH_NONE,
36 	/* The dialog should not be redrawn or refreshed again */
37 	REFRESH_STOP,
38 };
39 
40 typedef enum dlg_refresh_code (*dialog_refresh_handler_T)(struct dialog_data *, void *);
41 
42 struct dialog_refresh {
43 	dialog_refresh_handler_T handler;
44 	void *data;
45 	timer_id_T timer;
46 };
47 
48 struct dialog {
49 	unsigned char *title;
50 	void *udata;
51 	void *udata2;
52 	struct dialog_refresh *refresh;
53 
54 	void (*layouter)(struct dialog_data *);
55 	widget_handler_status_T (*handle_event)(struct dialog_data *);
56 	void (*abort)(struct dialog_data *);
57 
58 	struct dialog_layout layout;
59 
60 	int number_of_widgets;
61 	struct widget widgets[1]; /* must be at end of struct */
62 };
63 
64 /* Allocate a struct dialog for n - 1 widgets, one is already reserved in struct.
65  * add_size bytes will be added. */
66 #define sizeof_dialog(n, add_size) \
67 	(sizeof(struct dialog) + ((n) - 1) * sizeof(struct widget) + (add_size))
68 
69 #define calloc_dialog(n, add_size) ((struct dialog *) mem_calloc(1, sizeof_dialog(n, add_size)))
70 
71 #define get_dialog_offset(dlg, n) \
72 	(((unsigned char *) dlg) + sizeof_dialog(n, 0))
73 
74 #define dialog_has_refresh(dlg_data) \
75 	((dlg_data)->dlg->refresh && (dlg_data)->dlg->refresh->timer != TIMER_ID_UNDEF)
76 
77 static inline int
dialog_max_width(struct terminal * term)78 dialog_max_width(struct terminal *term)
79 {
80 	int width = term->width * 9 / 10 - 2 * DIALOG_LB;
81 
82 	int_bounds(&width, 1, int_max(term->width - 2 * DIALOG_LB, 1));
83 
84 	return width;
85 }
86 
87 static inline int
dialog_max_height(struct terminal * term)88 dialog_max_height(struct terminal *term)
89 {
90 	int height = term->height * 9 / 10 - 2 * DIALOG_TB;
91 
92 	int_bounds(&height, 1, int_max(term->height - 2 * DIALOG_TB, 1));
93 
94 	return height;
95 }
96 
97 struct dialog_data {
98 	struct window *win;
99 	struct dialog *dlg;
100 	struct memory_list *ml;
101 
102 	struct box box;
103 	int number_of_widgets;
104 	int selected_widget_id;
105 	struct term_event *term_event;
106 
107 	struct widget_data widgets_data[1]; /* must be at end of struct */
108 };
109 
110 
111 struct dialog_data *do_dialog(struct terminal *, struct dialog *,
112 			      struct memory_list *);
113 
114 /* Draws the dialog background and shadow */
115 void draw_dialog(struct dialog_data *dlg_data, int width, int height);
116 
117 /* Draws the dialog borders and layouter if @layout is non zerro. Finally all
118  * dialog items are redisplayed. */
119 void redraw_dialog(struct dialog_data *dlg_data, int layout);
120 
121 widget_handler_status_T ok_dialog(struct dialog_data *, struct widget_data *);
122 widget_handler_status_T cancel_dialog(struct dialog_data *, struct widget_data *);
123 widget_handler_status_T clear_dialog(struct dialog_data *, struct widget_data *);
124 int check_dialog(struct dialog_data *);
125 int update_dialog_data(struct dialog_data *);
126 void generic_dialog_layouter(struct dialog_data *dlg_data);
127 void refresh_dialog(struct dialog_data *, dialog_refresh_handler_T handler, void *data);
128 
129 #define selected_widget(dlg_data) (&(dlg_data)->widgets_data[(dlg_data)->selected_widget_id])
130 
131 void select_widget(struct dialog_data *dlg_data, struct widget_data *widget_data);
132 struct widget_data *select_widget_by_id(struct dialog_data *dlg_data, int i);
133 
134 #define before_widgets(dlg_data) (&(dlg_data)->widgets_data[-1])
135 #define end_of_widgets(dlg_data) (&(dlg_data)->widgets_data[(dlg_data)->number_of_widgets])
136 #define first_widget(dlg_data) (&(dlg_data)->widgets_data[0])
137 #define last_widget(dlg_data) (&(dlg_data)->widgets_data[(dlg_data)->number_of_widgets - 1])
138 
139 #define foreach_widget(dlg_data, widget_data) \
140 	for ((widget_data) = first_widget(dlg_data); \
141 	     (widget_data) != end_of_widgets(dlg_data); \
142 	     (widget_data)++)
143 
144 #define foreach_widget_back(dlg_data, widget_data) \
145 	for ((widget_data) = last_widget(dlg_data); \
146 	     (widget_data) != before_widgets(dlg_data); \
147 	     (widget_data)--)
148 
149 #define is_selected_widget(dlg_data, widget_data) ((widget_data) == selected_widget(dlg_data))
150 
151 #define add_dlg_end(dlg, n)						\
152 	do {								\
153 		assert(n == (dlg)->number_of_widgets);			\
154 	} while (0)
155 
156 #endif
157