xref: /freebsd/contrib/dialog/arrows.c (revision 6f9c8e5b074419423648ffb89b83fd2f257e90b7)
1 /*
2  *  $Id: arrows.c,v 1.33 2011/01/19 00:27:53 tom Exp $
3  *
4  *  arrows.c -- draw arrows to indicate end-of-range for lists
5  *
6  *  Copyright 2000-2010,2011	Thomas E. Dickey
7  *
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.
11  *
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.
16  *
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.
22  */
23 
24 #include <dialog.h>
25 
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
38 
39 #ifdef HAVE_COLOR
40 static chtype
41 merge_colors(chtype foreground, chtype background)
42 {
43     chtype result = foreground;
44     if ((foreground & A_COLOR) != (background & A_COLOR)) {
45 	short fg_f, bg_f;
46 	short fg_b, bg_b;
47 	short fg_pair = (short) PAIR_NUMBER(foreground);
48 	short bg_pair = (short) PAIR_NUMBER(background);
49 
50 	if (pair_content(fg_pair, &fg_f, &bg_f) != ERR
51 	    && pair_content(bg_pair, &fg_b, &bg_b) != ERR) {
52 	    result &= ~A_COLOR;
53 	    result |= dlg_color_pair(fg_f, bg_b);
54 	}
55     }
56     return result;
57 }
58 #else
59 #define merge_colors(f,b) (f)
60 #endif
61 
62 void
63 dlg_draw_arrows2(WINDOW *win,
64 		 int top_arrow,
65 		 int bottom_arrow,
66 		 int x,
67 		 int top,
68 		 int bottom,
69 		 chtype attr,
70 		 chtype borderattr)
71 {
72     chtype save = dlg_get_attrs(win);
73     int cur_x, cur_y;
74     int limit_x = getmaxx(win);
75     bool draw_top = TRUE;
76 
77     getyx(win, cur_y, cur_x);
78 
79     /*
80      * If we're drawing a centered title, do not overwrite with the arrows.
81      */
82     if (dialog_vars.title) {
83 	int have = (limit_x - dlg_count_columns(dialog_vars.title)) / 2;
84 	int need = x + 5;
85 	if (need > have)
86 	    draw_top = FALSE;
87     }
88 
89     if (draw_top) {
90 	(void) wmove(win, top, x);
91 	if (top_arrow) {
92 	    wattrset(win, merge_colors(uarrow_attr, attr));
93 	    (void) add_acs(win, ACS_UARROW);
94 	    (void) waddstr(win, "(-)");
95 	} else {
96 	    wattrset(win, attr);
97 	    (void) whline(win, dlg_boxchar(ACS_HLINE), 4);
98 	}
99     }
100     mouse_mkbutton(top, x - 1, 6, KEY_PPAGE);
101 
102     (void) wmove(win, bottom, x);
103     if (bottom_arrow) {
104 	wattrset(win, merge_colors(darrow_attr, attr));
105 	(void) add_acs(win, ACS_DARROW);
106 	(void) waddstr(win, "(+)");
107     } else {
108 	wattrset(win, borderattr);
109 	(void) whline(win, dlg_boxchar(ACS_HLINE), 4);
110     }
111     mouse_mkbutton(bottom, x - 1, 6, KEY_NPAGE);
112 
113     (void) wmove(win, cur_y, cur_x);
114     wrefresh(win);
115 
116     wattrset(win, save);
117 }
118 
119 void
120 dlg_draw_scrollbar(WINDOW *win,
121 		   long first_data,
122 		   long this_data,
123 		   long next_data,
124 		   long total_data,
125 		   int left,
126 		   int right,
127 		   int top,
128 		   int bottom,
129 		   chtype attr,
130 		   chtype borderattr)
131 {
132     char buffer[80];
133     int percent;
134     int len;
135     int oldy, oldx, maxy, maxx;
136 
137     chtype save = dlg_get_attrs(win);
138     int top_arrow = (first_data != 0);
139     int bottom_arrow = (next_data < total_data);
140 
141     getyx(win, oldy, oldx);
142     getmaxyx(win, maxy, maxx);
143 
144     if (bottom_arrow || top_arrow || dialog_state.use_scrollbar) {
145 	percent = (!total_data
146 		   ? 100
147 		   : (int) ((next_data * 100)
148 			    / total_data));
149 
150 	if (percent < 0)
151 	    percent = 0;
152 	else if (percent > 100)
153 	    percent = 100;
154 
155 	wattrset(win, position_indicator_attr);
156 	(void) sprintf(buffer, "%d%%", percent);
157 	(void) wmove(win, bottom, right - 7);
158 	(void) waddstr(win, buffer);
159 	if ((len = dlg_count_columns(buffer)) < 4) {
160 	    wattrset(win, border_attr);
161 	    whline(win, dlg_boxchar(ACS_HLINE), 4 - len);
162 	}
163     }
164 #define BARSIZE(num) (int) (((all_high * (num)) + all_high - 1) / total_data)
165 
166     if (dialog_state.use_scrollbar) {
167 	int all_high = (bottom - top - 1);
168 
169 	if (total_data > 0 && all_high > 0) {
170 	    int bar_high;
171 	    int bar_y;
172 
173 	    bar_high = BARSIZE(next_data - this_data);
174 	    if (bar_high <= 0)
175 		bar_high = 1;
176 
177 	    if (bar_high < all_high) {
178 		wmove(win, top + 1, right);
179 
180 		wattrset(win, save);
181 		wvline(win, ACS_VLINE | A_REVERSE, all_high);
182 
183 		bar_y = BARSIZE(this_data);
184 		if (bar_y > all_high - bar_high)
185 		    bar_y = all_high - bar_high;
186 
187 		wmove(win, top + 1 + bar_y, right);
188 
189 		wattrset(win, position_indicator_attr);
190 		wattron(win, A_REVERSE);
191 		wvline(win, ACS_BLOCK, bar_high);
192 	    }
193 	}
194     }
195     dlg_draw_arrows2(win,
196 		     top_arrow,
197 		     bottom_arrow,
198 		     left + ARROWS_COL,
199 		     top,
200 		     bottom,
201 		     attr,
202 		     borderattr);
203 
204     wattrset(win, save);
205     wmove(win, oldy, oldx);
206 }
207 
208 void
209 dlg_draw_arrows(WINDOW *win,
210 		int top_arrow,
211 		int bottom_arrow,
212 		int x,
213 		int top,
214 		int bottom)
215 {
216     dlg_draw_arrows2(win,
217 		     top_arrow,
218 		     bottom_arrow,
219 		     x,
220 		     top,
221 		     bottom,
222 		     menubox_attr,
223 		     menubox_border_attr);
224 }
225