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