rewrite: update default dumb and smart prefixes
[elinks/elinks-j605.git] / src / bfu / dialog.h
blobe543d8c85a9a1357392015ae6395aaed5302d963
1 #ifndef EL__BFU_DIALOG_H
2 #define EL__BFU_DIALOG_H
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"
12 struct dialog_data;
13 struct term_event;
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;
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,
40 typedef enum dlg_refresh_code (*dialog_refresh_handler_T)(struct dialog_data *, void *);
42 struct dialog_refresh {
43 dialog_refresh_handler_T handler;
44 void *data;
45 timer_id_T timer;
48 struct dialog {
49 unsigned char *title;
50 void *udata;
51 void *udata2;
52 struct dialog_refresh *refresh;
54 void (*layouter)(struct dialog_data *);
55 widget_handler_status_T (*handle_event)(struct dialog_data *);
56 void (*abort)(struct dialog_data *);
58 struct dialog_layout layout;
60 /** How many widgets have been added to this dialog.
61 * The #widgets array may be larger than this if some
62 * of the intended widgets have not yet been added. */
63 int number_of_widgets;
65 struct widget widgets[1]; /* must be at end of struct */
67 /* There may be additional data after widgets[]. The size and
68 * format of the additional data is specific to each dialog.
69 * Dialogs typically place the buffer of each WIDGET_FIELD
70 * widget somewhere in this additional-data area so that the
71 * buffer need not be allocated and freed separately.
73 * When constructing a dialog, give the size of the additional
74 * data as a parameter to sizeof_dialog() and calloc_dialog().
75 * Then, use get_dialog_offset() to get the address of the
76 * additional data. */
79 /** Gets the amount of memory needed for a dialog.
81 * @param n
82 * How many widgets there will be in the dialog.
83 * @param add_size
84 * The size of the additional data, in bytes.
86 * @return
87 * The total amount of memory needed for struct dialog, the widgets,
88 * and the additional data. This however does not include struct
89 * dialog_data.
91 * struct dialog already reserves memory for one widget. */
92 #define sizeof_dialog(n, add_size) \
93 (sizeof(struct dialog) + ((n) - 1) * sizeof(struct widget) + (add_size))
95 /** Allocates and clears memory for a dialog.
97 * @param n
98 * How many widgets there will be in the dialog.
99 * @param add_size
100 * The size of the additional data, in bytes.
102 * @return
103 * struct dialog *; or NULL if out of memory.
105 * This macro sets dialog.number_of_widgets = 0.
106 * The caller can then add widgets to the dialog
107 * until dialog.number_of_widgets reaches @a n. */
108 #define calloc_dialog(n, add_size) ((struct dialog *) mem_calloc(1, sizeof_dialog(n, add_size)))
110 /** Gets the address of the additional data of a dialog.
112 * @param dlg
113 * struct dialog *dlg; the dialog that carries the additional data.
114 * @param n
115 * For how many widgets the dialog was allocated; i.e. the
116 * @c n parameter of sizeof_dialog() and calloc_dialog().
117 * This macro does not read dialog.number_of_widgets because
118 * that is typically still zero when this macro is used.
120 * @return
121 * The address of the additional data. */
122 #define get_dialog_offset(dlg, n) \
123 (((unsigned char *) dlg) + sizeof_dialog(n, 0))
125 #define dialog_has_refresh(dlg_data) \
126 ((dlg_data)->dlg->refresh && (dlg_data)->dlg->refresh->timer != TIMER_ID_UNDEF)
128 static inline int
129 dialog_max_width(struct terminal *term)
131 int width = term->width * 9 / 10 - 2 * DIALOG_LB;
133 int_bounds(&width, 1, int_max(term->width - 2 * DIALOG_LB, 1));
135 return width;
138 static inline int
139 dialog_max_height(struct terminal *term)
141 int height = term->height * 9 / 10 - 2 * DIALOG_TB;
143 int_bounds(&height, 1, int_max(term->height - 2 * DIALOG_TB, 1));
145 return height;
148 struct dialog_data {
149 struct window *win;
150 struct dialog *dlg;
151 struct memory_list *ml;
153 /** Size and location of the dialog box, excluding the drop shadow.
154 * This includes the outer border and the frame.
155 * The coordinates are relative to the terminal. */
156 struct box box;
158 /** Size and location of the widget area and the inner border.
159 * This is the area in which widgets can be drawn.
160 * The frame of the dialog box is drawn around this area,
161 * and the outer border is around the frame.
162 * The coordinates are relative to the terminal. */
163 struct box real_box;
165 /** Vertical scrolling of the widget area of the dialog box.
166 * Widget Y screen coordinate = widget_data.box.y - dialog_data.y.
167 * Initially, this is 0 and the coordinate system of the widget area
168 * matches the coordinate system of the terminal.
169 * Horizontal scrolling of dialog boxes has not been implemented. */
170 int y;
172 int number_of_widgets;
173 int selected_widget_id;
174 struct term_event *term_event;
176 struct widget_data widgets_data[1]; /* must be at end of struct */
180 struct dialog_data *do_dialog(struct terminal *, struct dialog *,
181 struct memory_list *);
183 /* Draws the dialog background and shadow */
184 void draw_dialog(struct dialog_data *dlg_data, int width, int height);
186 /* Draws the dialog borders and layouter if @layout is non zerro. Finally all
187 * dialog items are redisplayed. */
188 void redraw_dialog(struct dialog_data *dlg_data, int layout);
190 widget_handler_status_T ok_dialog(struct dialog_data *, struct widget_data *);
191 widget_handler_status_T cancel_dialog(struct dialog_data *, struct widget_data *);
192 widget_handler_status_T clear_dialog(struct dialog_data *, struct widget_data *);
193 int check_dialog(struct dialog_data *);
194 int update_dialog_data(struct dialog_data *);
195 void generic_dialog_layouter(struct dialog_data *dlg_data);
196 void refresh_dialog(struct dialog_data *, dialog_refresh_handler_T handler, void *data);
198 #define selected_widget(dlg_data) (&(dlg_data)->widgets_data[(dlg_data)->selected_widget_id])
200 void select_widget(struct dialog_data *dlg_data, struct widget_data *widget_data);
201 struct widget_data *select_widget_by_id(struct dialog_data *dlg_data, int i);
203 #define before_widgets(dlg_data) (&(dlg_data)->widgets_data[-1])
204 #define end_of_widgets(dlg_data) (&(dlg_data)->widgets_data[(dlg_data)->number_of_widgets])
205 #define first_widget(dlg_data) (&(dlg_data)->widgets_data[0])
206 #define last_widget(dlg_data) (&(dlg_data)->widgets_data[(dlg_data)->number_of_widgets - 1])
208 #define foreach_widget(dlg_data, widget_data) \
209 for ((widget_data) = first_widget(dlg_data); \
210 (widget_data) != end_of_widgets(dlg_data); \
211 (widget_data)++)
213 #define foreach_widget_back(dlg_data, widget_data) \
214 for ((widget_data) = last_widget(dlg_data); \
215 (widget_data) != before_widgets(dlg_data); \
216 (widget_data)--)
218 #define is_selected_widget(dlg_data, widget_data) ((widget_data) == selected_widget(dlg_data))
220 #define add_dlg_end(dlg, n) \
221 do { \
222 assert(n == (dlg)->number_of_widgets); \
223 } while (0)
225 #endif