1217309Snwhitehorn/*
2255852Sdteske *  $Id: arrows.c,v 1.51 2013/09/02 15:10:09 tom Exp $
3217309Snwhitehorn *
4217309Snwhitehorn *  arrows.c -- draw arrows to indicate end-of-range for lists
5217309Snwhitehorn *
6251843Sbapt *  Copyright 2000-2012,2013	Thomas E. Dickey
7217309Snwhitehorn *
8217309Snwhitehorn *  This program is free software; you can redistribute it and/or modify
9217309Snwhitehorn *  it under the terms of the GNU Lesser General Public License, version 2.1
10217309Snwhitehorn *  as published by the Free Software Foundation.
11217309Snwhitehorn *
12217309Snwhitehorn *  This program is distributed in the hope that it will be useful, but
13217309Snwhitehorn *  WITHOUT ANY WARRANTY; without even the implied warranty of
14217309Snwhitehorn *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15217309Snwhitehorn *  Lesser General Public License for more details.
16217309Snwhitehorn *
17217309Snwhitehorn *  You should have received a copy of the GNU Lesser General Public
18217309Snwhitehorn *  License along with this program; if not, write to
19217309Snwhitehorn *	Free Software Foundation, Inc.
20217309Snwhitehorn *	51 Franklin St., Fifth Floor
21217309Snwhitehorn *	Boston, MA 02110, USA.
22217309Snwhitehorn */
23217309Snwhitehorn
24217309Snwhitehorn#include <dialog.h>
25217309Snwhitehorn
26217309Snwhitehorn#ifdef USE_WIDE_CURSES
27220749Snwhitehorn#if defined(CURSES_WACS_ARRAY) && !defined(CURSES_WACS_SYMBOLS)
28220749Snwhitehorn/* workaround for NetBSD 5.1 curses */
29220749Snwhitehorn#undef WACS_DARROW
30220749Snwhitehorn#undef WACS_UARROW
31220749Snwhitehorn#define WACS_DARROW &(CURSES_WACS_ARRAY['.'])
32220749Snwhitehorn#define WACS_UARROW &(CURSES_WACS_ARRAY['-'])
33220749Snwhitehorn#endif
34217309Snwhitehorn#define add_acs(win, code) wadd_wch(win, W ## code)
35217309Snwhitehorn#else
36217309Snwhitehorn#define add_acs(win, code) waddch(win, dlg_boxchar(code))
37217309Snwhitehorn#endif
38217309Snwhitehorn
39224014Snwhitehorn/* size of decorations */
40224014Snwhitehorn#define ON_LEFT 4
41224014Snwhitehorn#define ON_RIGHT 3
42224014Snwhitehorn
43217309Snwhitehorn#ifdef HAVE_COLOR
44217309Snwhitehornstatic chtype
45217309Snwhitehornmerge_colors(chtype foreground, chtype background)
46217309Snwhitehorn{
47217309Snwhitehorn    chtype result = foreground;
48217309Snwhitehorn    if ((foreground & A_COLOR) != (background & A_COLOR)) {
49217309Snwhitehorn	short fg_f, bg_f;
50217309Snwhitehorn	short fg_b, bg_b;
51217309Snwhitehorn	short fg_pair = (short) PAIR_NUMBER(foreground);
52217309Snwhitehorn	short bg_pair = (short) PAIR_NUMBER(background);
53217309Snwhitehorn
54217309Snwhitehorn	if (pair_content(fg_pair, &fg_f, &bg_f) != ERR
55217309Snwhitehorn	    && pair_content(bg_pair, &fg_b, &bg_b) != ERR) {
56217309Snwhitehorn	    result &= ~A_COLOR;
57217309Snwhitehorn	    result |= dlg_color_pair(fg_f, bg_b);
58217309Snwhitehorn	}
59217309Snwhitehorn    }
60217309Snwhitehorn    return result;
61217309Snwhitehorn}
62217309Snwhitehorn#else
63217309Snwhitehorn#define merge_colors(f,b) (f)
64217309Snwhitehorn#endif
65217309Snwhitehorn
66224014Snwhitehorn/*
67224014Snwhitehorn * If we have help-line text, e.g., from "--hline", draw it between the other
68224014Snwhitehorn * decorations at the bottom of the dialog window.
69224014Snwhitehorn */
70217309Snwhitehornvoid
71224014Snwhitehorndlg_draw_helpline(WINDOW *win, bool decorations)
72224014Snwhitehorn{
73224014Snwhitehorn    int cur_x, cur_y;
74224014Snwhitehorn    int bottom;
75224014Snwhitehorn
76224014Snwhitehorn    if (dialog_vars.help_line != 0
77255852Sdteske	&& dialog_vars.help_line[0] != 0
78224014Snwhitehorn	&& (bottom = getmaxy(win) - 1) > 0) {
79224014Snwhitehorn	chtype attr = A_NORMAL;
80255852Sdteske	int cols = dlg_count_columns(dialog_vars.help_line);
81224014Snwhitehorn	int other = decorations ? (ON_LEFT + ON_RIGHT) : 0;
82224014Snwhitehorn	int avail = (getmaxx(win) - other - 2);
83251843Sbapt	int limit = dlg_count_real_columns(dialog_vars.help_line) + 2;
84224014Snwhitehorn
85251843Sbapt	if (limit < avail) {
86224014Snwhitehorn	    getyx(win, cur_y, cur_x);
87224014Snwhitehorn	    other = decorations ? ON_LEFT : 0;
88224014Snwhitehorn	    (void) wmove(win, bottom, other + (avail - limit) / 2);
89224014Snwhitehorn	    waddch(win, '[');
90255852Sdteske	    dlg_print_text(win, dialog_vars.help_line, cols, &attr);
91224014Snwhitehorn	    waddch(win, ']');
92224014Snwhitehorn	    wmove(win, cur_y, cur_x);
93224014Snwhitehorn	}
94224014Snwhitehorn    }
95224014Snwhitehorn}
96224014Snwhitehorn
97224014Snwhitehornvoid
98217309Snwhitehorndlg_draw_arrows2(WINDOW *win,
99217309Snwhitehorn		 int top_arrow,
100217309Snwhitehorn		 int bottom_arrow,
101217309Snwhitehorn		 int x,
102217309Snwhitehorn		 int top,
103217309Snwhitehorn		 int bottom,
104217309Snwhitehorn		 chtype attr,
105217309Snwhitehorn		 chtype borderattr)
106217309Snwhitehorn{
107220749Snwhitehorn    chtype save = dlg_get_attrs(win);
108217309Snwhitehorn    int cur_x, cur_y;
109217309Snwhitehorn    int limit_x = getmaxx(win);
110217309Snwhitehorn    bool draw_top = TRUE;
111251843Sbapt    bool is_toplevel = (wgetparent(win) == stdscr);
112217309Snwhitehorn
113217309Snwhitehorn    getyx(win, cur_y, cur_x);
114217309Snwhitehorn
115217309Snwhitehorn    /*
116217309Snwhitehorn     * If we're drawing a centered title, do not overwrite with the arrows.
117217309Snwhitehorn     */
118251843Sbapt    if (dialog_vars.title && is_toplevel && (top - getbegy(win)) < MARGIN) {
119217309Snwhitehorn	int have = (limit_x - dlg_count_columns(dialog_vars.title)) / 2;
120217309Snwhitehorn	int need = x + 5;
121217309Snwhitehorn	if (need > have)
122217309Snwhitehorn	    draw_top = FALSE;
123217309Snwhitehorn    }
124217309Snwhitehorn
125217309Snwhitehorn    if (draw_top) {
126217309Snwhitehorn	(void) wmove(win, top, x);
127217309Snwhitehorn	if (top_arrow) {
128251843Sbapt	    (void) wattrset(win, merge_colors(uarrow_attr, attr));
129217309Snwhitehorn	    (void) add_acs(win, ACS_UARROW);
130217309Snwhitehorn	    (void) waddstr(win, "(-)");
131217309Snwhitehorn	} else {
132251843Sbapt	    (void) wattrset(win, attr);
133224014Snwhitehorn	    (void) whline(win, dlg_boxchar(ACS_HLINE), ON_LEFT);
134217309Snwhitehorn	}
135217309Snwhitehorn    }
136217309Snwhitehorn    mouse_mkbutton(top, x - 1, 6, KEY_PPAGE);
137217309Snwhitehorn
138217309Snwhitehorn    (void) wmove(win, bottom, x);
139217309Snwhitehorn    if (bottom_arrow) {
140251843Sbapt	(void) wattrset(win, merge_colors(darrow_attr, borderattr));
141217309Snwhitehorn	(void) add_acs(win, ACS_DARROW);
142217309Snwhitehorn	(void) waddstr(win, "(+)");
143217309Snwhitehorn    } else {
144251843Sbapt	(void) wattrset(win, borderattr);
145224014Snwhitehorn	(void) whline(win, dlg_boxchar(ACS_HLINE), ON_LEFT);
146217309Snwhitehorn    }
147217309Snwhitehorn    mouse_mkbutton(bottom, x - 1, 6, KEY_NPAGE);
148217309Snwhitehorn
149217309Snwhitehorn    (void) wmove(win, cur_y, cur_x);
150217309Snwhitehorn    wrefresh(win);
151217309Snwhitehorn
152251843Sbapt    (void) wattrset(win, save);
153217309Snwhitehorn}
154217309Snwhitehorn
155217309Snwhitehornvoid
156217309Snwhitehorndlg_draw_scrollbar(WINDOW *win,
157217309Snwhitehorn		   long first_data,
158217309Snwhitehorn		   long this_data,
159217309Snwhitehorn		   long next_data,
160217309Snwhitehorn		   long total_data,
161217309Snwhitehorn		   int left,
162217309Snwhitehorn		   int right,
163217309Snwhitehorn		   int top,
164217309Snwhitehorn		   int bottom,
165217309Snwhitehorn		   chtype attr,
166217309Snwhitehorn		   chtype borderattr)
167217309Snwhitehorn{
168217309Snwhitehorn    char buffer[80];
169217309Snwhitehorn    int percent;
170217309Snwhitehorn    int len;
171251843Sbapt    int oldy, oldx;
172217309Snwhitehorn
173220749Snwhitehorn    chtype save = dlg_get_attrs(win);
174217309Snwhitehorn    int top_arrow = (first_data != 0);
175217309Snwhitehorn    int bottom_arrow = (next_data < total_data);
176217309Snwhitehorn
177217309Snwhitehorn    getyx(win, oldy, oldx);
178217309Snwhitehorn
179224014Snwhitehorn    dlg_draw_helpline(win, TRUE);
180217309Snwhitehorn    if (bottom_arrow || top_arrow || dialog_state.use_scrollbar) {
181217309Snwhitehorn	percent = (!total_data
182217309Snwhitehorn		   ? 100
183217309Snwhitehorn		   : (int) ((next_data * 100)
184217309Snwhitehorn			    / total_data));
185217309Snwhitehorn
186217309Snwhitehorn	if (percent < 0)
187217309Snwhitehorn	    percent = 0;
188217309Snwhitehorn	else if (percent > 100)
189217309Snwhitehorn	    percent = 100;
190217309Snwhitehorn
191251843Sbapt	(void) wattrset(win, position_indicator_attr);
192217309Snwhitehorn	(void) sprintf(buffer, "%d%%", percent);
193217309Snwhitehorn	(void) wmove(win, bottom, right - 7);
194217309Snwhitehorn	(void) waddstr(win, buffer);
195217309Snwhitehorn	if ((len = dlg_count_columns(buffer)) < 4) {
196251843Sbapt	    (void) wattrset(win, border_attr);
197217309Snwhitehorn	    whline(win, dlg_boxchar(ACS_HLINE), 4 - len);
198217309Snwhitehorn	}
199217309Snwhitehorn    }
200251843Sbapt#define BARSIZE(num) (int) (0.5 + (double) ((all_high * (int) (num)) / (double) total_data))
201251843Sbapt#define ORDSIZE(num) (int) ((double) ((all_high * (int) (num)) / (double) all_diff))
202217309Snwhitehorn
203217309Snwhitehorn    if (dialog_state.use_scrollbar) {
204217309Snwhitehorn	int all_high = (bottom - top - 1);
205217309Snwhitehorn
206251843Sbapt	this_data = MAX(0, this_data);
207251843Sbapt
208217309Snwhitehorn	if (total_data > 0 && all_high > 0) {
209251843Sbapt	    int all_diff = (int) (total_data + 1);
210251843Sbapt	    int bar_diff = (int) (next_data + 1 - this_data);
211217309Snwhitehorn	    int bar_high;
212217309Snwhitehorn	    int bar_y;
213217309Snwhitehorn
214251843Sbapt	    bar_high = ORDSIZE(bar_diff);
215217309Snwhitehorn	    if (bar_high <= 0)
216217309Snwhitehorn		bar_high = 1;
217217309Snwhitehorn
218217309Snwhitehorn	    if (bar_high < all_high) {
219251843Sbapt		int bar_last = BARSIZE(next_data);
220251843Sbapt
221217309Snwhitehorn		wmove(win, top + 1, right);
222217309Snwhitehorn
223251843Sbapt		(void) wattrset(win, save);
224217309Snwhitehorn		wvline(win, ACS_VLINE | A_REVERSE, all_high);
225217309Snwhitehorn
226251843Sbapt		bar_y = ORDSIZE(this_data);
227251843Sbapt		if (bar_y >= bar_last && bar_y > 0)
228251843Sbapt		    bar_y = bar_last - 1;
229251843Sbapt		if (bar_last - bar_y > bar_high && bar_high > 1)
230251843Sbapt		    ++bar_y;
231251843Sbapt		bar_last = MIN(bar_last, all_high);
232217309Snwhitehorn
233217309Snwhitehorn		wmove(win, top + 1 + bar_y, right);
234217309Snwhitehorn
235251843Sbapt		(void) wattrset(win, position_indicator_attr);
236217309Snwhitehorn		wattron(win, A_REVERSE);
237251843Sbapt#if defined(WACS_BLOCK) && defined(NCURSES_VERSION) && defined(USE_WIDE_CURSES)
238251843Sbapt		wvline_set(win, WACS_BLOCK, bar_last - bar_y);
239251843Sbapt#else
240251843Sbapt		wvline(win, ACS_BLOCK, bar_last - bar_y);
241251843Sbapt#endif
242217309Snwhitehorn	    }
243217309Snwhitehorn	}
244217309Snwhitehorn    }
245217309Snwhitehorn    dlg_draw_arrows2(win,
246217309Snwhitehorn		     top_arrow,
247217309Snwhitehorn		     bottom_arrow,
248217309Snwhitehorn		     left + ARROWS_COL,
249217309Snwhitehorn		     top,
250217309Snwhitehorn		     bottom,
251217309Snwhitehorn		     attr,
252217309Snwhitehorn		     borderattr);
253217309Snwhitehorn
254251843Sbapt    (void) wattrset(win, save);
255217309Snwhitehorn    wmove(win, oldy, oldx);
256217309Snwhitehorn}
257217309Snwhitehorn
258217309Snwhitehornvoid
259217309Snwhitehorndlg_draw_arrows(WINDOW *win,
260217309Snwhitehorn		int top_arrow,
261217309Snwhitehorn		int bottom_arrow,
262217309Snwhitehorn		int x,
263217309Snwhitehorn		int top,
264217309Snwhitehorn		int bottom)
265217309Snwhitehorn{
266224014Snwhitehorn    dlg_draw_helpline(win, TRUE);
267217309Snwhitehorn    dlg_draw_arrows2(win,
268217309Snwhitehorn		     top_arrow,
269217309Snwhitehorn		     bottom_arrow,
270217309Snwhitehorn		     x,
271217309Snwhitehorn		     top,
272217309Snwhitehorn		     bottom,
273251843Sbapt		     menubox_border2_attr,
274217309Snwhitehorn		     menubox_border_attr);
275217309Snwhitehorn}
276