kernel - Fix races created by a comedy of circumstansces (3)
[dragonfly.git] / contrib / dialog / arrows.c
blob44a90dfdcba430d52f8ec4d145ad6f94c8e4a031
1 /*
2 * $Id: arrows.c,v 1.51 2013/09/02 15:10:09 tom Exp $
4 * arrows.c -- draw arrows to indicate end-of-range for lists
6 * Copyright 2000-2012,2013 Thomas E. Dickey
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License, version 2.1
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to
19 * Free Software Foundation, Inc.
20 * 51 Franklin St., Fifth Floor
21 * Boston, MA 02110, USA.
24 #include <dialog.h>
26 #ifdef USE_WIDE_CURSES
27 #if defined(CURSES_WACS_ARRAY) && !defined(CURSES_WACS_SYMBOLS)
28 /* workaround for NetBSD 5.1 curses */
29 #undef WACS_DARROW
30 #undef WACS_UARROW
31 #define WACS_DARROW &(CURSES_WACS_ARRAY['.'])
32 #define WACS_UARROW &(CURSES_WACS_ARRAY['-'])
33 #endif
34 #define add_acs(win, code) wadd_wch(win, W ## code)
35 #else
36 #define add_acs(win, code) waddch(win, dlg_boxchar(code))
37 #endif
39 /* size of decorations */
40 #define ON_LEFT 4
41 #define ON_RIGHT 3
43 #ifdef HAVE_COLOR
44 static chtype
45 merge_colors(chtype foreground, chtype background)
47 chtype result = foreground;
48 if ((foreground & A_COLOR) != (background & A_COLOR)) {
49 short fg_f, bg_f;
50 short fg_b, bg_b;
51 short fg_pair = (short) PAIR_NUMBER(foreground);
52 short bg_pair = (short) PAIR_NUMBER(background);
54 if (pair_content(fg_pair, &fg_f, &bg_f) != ERR
55 && pair_content(bg_pair, &fg_b, &bg_b) != ERR) {
56 result &= ~A_COLOR;
57 result |= dlg_color_pair(fg_f, bg_b);
60 return result;
62 #else
63 #define merge_colors(f,b) (f)
64 #endif
67 * If we have help-line text, e.g., from "--hline", draw it between the other
68 * decorations at the bottom of the dialog window.
70 void
71 dlg_draw_helpline(WINDOW *win, bool decorations)
73 int cur_x, cur_y;
74 int bottom;
76 if (dialog_vars.help_line != 0
77 && dialog_vars.help_line[0] != 0
78 && (bottom = getmaxy(win) - 1) > 0) {
79 chtype attr = A_NORMAL;
80 int cols = dlg_count_columns(dialog_vars.help_line);
81 int other = decorations ? (ON_LEFT + ON_RIGHT) : 0;
82 int avail = (getmaxx(win) - other - 2);
83 int limit = dlg_count_real_columns(dialog_vars.help_line) + 2;
85 if (limit < avail) {
86 getyx(win, cur_y, cur_x);
87 other = decorations ? ON_LEFT : 0;
88 (void) wmove(win, bottom, other + (avail - limit) / 2);
89 waddch(win, '[');
90 dlg_print_text(win, dialog_vars.help_line, cols, &attr);
91 waddch(win, ']');
92 wmove(win, cur_y, cur_x);
97 void
98 dlg_draw_arrows2(WINDOW *win,
99 int top_arrow,
100 int bottom_arrow,
101 int x,
102 int top,
103 int bottom,
104 chtype attr,
105 chtype borderattr)
107 chtype save = dlg_get_attrs(win);
108 int cur_x, cur_y;
109 int limit_x = getmaxx(win);
110 bool draw_top = TRUE;
111 bool is_toplevel = (wgetparent(win) == stdscr);
113 getyx(win, cur_y, cur_x);
116 * If we're drawing a centered title, do not overwrite with the arrows.
118 if (dialog_vars.title && is_toplevel && (top - getbegy(win)) < MARGIN) {
119 int have = (limit_x - dlg_count_columns(dialog_vars.title)) / 2;
120 int need = x + 5;
121 if (need > have)
122 draw_top = FALSE;
125 if (draw_top) {
126 (void) wmove(win, top, x);
127 if (top_arrow) {
128 (void) wattrset(win, merge_colors(uarrow_attr, attr));
129 (void) add_acs(win, ACS_UARROW);
130 (void) waddstr(win, "(-)");
131 } else {
132 (void) wattrset(win, attr);
133 (void) whline(win, dlg_boxchar(ACS_HLINE), ON_LEFT);
136 mouse_mkbutton(top, x - 1, 6, KEY_PPAGE);
138 (void) wmove(win, bottom, x);
139 if (bottom_arrow) {
140 (void) wattrset(win, merge_colors(darrow_attr, borderattr));
141 (void) add_acs(win, ACS_DARROW);
142 (void) waddstr(win, "(+)");
143 } else {
144 (void) wattrset(win, borderattr);
145 (void) whline(win, dlg_boxchar(ACS_HLINE), ON_LEFT);
147 mouse_mkbutton(bottom, x - 1, 6, KEY_NPAGE);
149 (void) wmove(win, cur_y, cur_x);
150 wrefresh(win);
152 (void) wattrset(win, save);
155 void
156 dlg_draw_scrollbar(WINDOW *win,
157 long first_data,
158 long this_data,
159 long next_data,
160 long total_data,
161 int left,
162 int right,
163 int top,
164 int bottom,
165 chtype attr,
166 chtype borderattr)
168 char buffer[80];
169 int percent;
170 int len;
171 int oldy, oldx;
173 chtype save = dlg_get_attrs(win);
174 int top_arrow = (first_data != 0);
175 int bottom_arrow = (next_data < total_data);
177 getyx(win, oldy, oldx);
179 dlg_draw_helpline(win, TRUE);
180 if (bottom_arrow || top_arrow || dialog_state.use_scrollbar) {
181 percent = (!total_data
182 ? 100
183 : (int) ((next_data * 100)
184 / total_data));
186 if (percent < 0)
187 percent = 0;
188 else if (percent > 100)
189 percent = 100;
191 (void) wattrset(win, position_indicator_attr);
192 (void) sprintf(buffer, "%d%%", percent);
193 (void) wmove(win, bottom, right - 7);
194 (void) waddstr(win, buffer);
195 if ((len = dlg_count_columns(buffer)) < 4) {
196 (void) wattrset(win, border_attr);
197 whline(win, dlg_boxchar(ACS_HLINE), 4 - len);
200 #define BARSIZE(num) (int) (0.5 + (double) ((all_high * (int) (num)) / (double) total_data))
201 #define ORDSIZE(num) (int) ((double) ((all_high * (int) (num)) / (double) all_diff))
203 if (dialog_state.use_scrollbar) {
204 int all_high = (bottom - top - 1);
206 this_data = MAX(0, this_data);
208 if (total_data > 0 && all_high > 0) {
209 int all_diff = (int) (total_data + 1);
210 int bar_diff = (int) (next_data + 1 - this_data);
211 int bar_high;
212 int bar_y;
214 bar_high = ORDSIZE(bar_diff);
215 if (bar_high <= 0)
216 bar_high = 1;
218 if (bar_high < all_high) {
219 int bar_last = BARSIZE(next_data);
221 wmove(win, top + 1, right);
223 (void) wattrset(win, save);
224 wvline(win, ACS_VLINE | A_REVERSE, all_high);
226 bar_y = ORDSIZE(this_data);
227 if (bar_y >= bar_last && bar_y > 0)
228 bar_y = bar_last - 1;
229 if (bar_last - bar_y > bar_high && bar_high > 1)
230 ++bar_y;
231 bar_last = MIN(bar_last, all_high);
233 wmove(win, top + 1 + bar_y, right);
235 (void) wattrset(win, position_indicator_attr);
236 wattron(win, A_REVERSE);
237 #if defined(WACS_BLOCK) && defined(NCURSES_VERSION) && defined(USE_WIDE_CURSES)
238 wvline_set(win, WACS_BLOCK, bar_last - bar_y);
239 #else
240 wvline(win, ACS_BLOCK, bar_last - bar_y);
241 #endif
245 dlg_draw_arrows2(win,
246 top_arrow,
247 bottom_arrow,
248 left + ARROWS_COL,
249 top,
250 bottom,
251 attr,
252 borderattr);
254 (void) wattrset(win, save);
255 wmove(win, oldy, oldx);
258 void
259 dlg_draw_arrows(WINDOW *win,
260 int top_arrow,
261 int bottom_arrow,
262 int x,
263 int top,
264 int bottom)
266 dlg_draw_helpline(win, TRUE);
267 dlg_draw_arrows2(win,
268 top_arrow,
269 bottom_arrow,
271 top,
272 bottom,
273 menubox_border2_attr,
274 menubox_border_attr);