]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/dialog/arrows.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / dialog / arrows.c
1 /*
2  *  $Id: arrows.c,v 1.36 2011/06/27 09:13:56 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 /* size of decorations */
40 #define ON_LEFT 4
41 #define ON_RIGHT 3
42
43 #ifdef HAVE_COLOR
44 static chtype
45 merge_colors(chtype foreground, chtype background)
46 {
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);
53
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);
58         }
59     }
60     return result;
61 }
62 #else
63 #define merge_colors(f,b) (f)
64 #endif
65
66 /*
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.
69  */
70 void
71 dlg_draw_helpline(WINDOW *win, bool decorations)
72 {
73     int cur_x, cur_y;
74     int bottom;
75
76     if (dialog_vars.help_line != 0
77         && (bottom = getmaxy(win) - 1) > 0) {
78         chtype attr = A_NORMAL;
79         const int *cols = dlg_index_columns(dialog_vars.help_line);
80         int other = decorations ? (ON_LEFT + ON_RIGHT) : 0;
81         int avail = (getmaxx(win) - other - 2);
82         int limit = dlg_limit_columns(dialog_vars.help_line, avail, 0);
83
84         if (limit > 0) {
85             getyx(win, cur_y, cur_x);
86             other = decorations ? ON_LEFT : 0;
87             (void) wmove(win, bottom, other + (avail - limit) / 2);
88             waddch(win, '[');
89             dlg_print_text(win, dialog_vars.help_line, cols[limit], &attr);
90             waddch(win, ']');
91             wmove(win, cur_y, cur_x);
92         }
93     }
94 }
95
96 void
97 dlg_draw_arrows2(WINDOW *win,
98                  int top_arrow,
99                  int bottom_arrow,
100                  int x,
101                  int top,
102                  int bottom,
103                  chtype attr,
104                  chtype borderattr)
105 {
106     chtype save = dlg_get_attrs(win);
107     int cur_x, cur_y;
108     int limit_x = getmaxx(win);
109     bool draw_top = TRUE;
110
111     getyx(win, cur_y, cur_x);
112
113     /*
114      * If we're drawing a centered title, do not overwrite with the arrows.
115      */
116     if (dialog_vars.title) {
117         int have = (limit_x - dlg_count_columns(dialog_vars.title)) / 2;
118         int need = x + 5;
119         if (need > have)
120             draw_top = FALSE;
121     }
122
123     if (draw_top) {
124         (void) wmove(win, top, x);
125         if (top_arrow) {
126             wattrset(win, merge_colors(uarrow_attr, attr));
127             (void) add_acs(win, ACS_UARROW);
128             (void) waddstr(win, "(-)");
129         } else {
130             wattrset(win, attr);
131             (void) whline(win, dlg_boxchar(ACS_HLINE), ON_LEFT);
132         }
133     }
134     mouse_mkbutton(top, x - 1, 6, KEY_PPAGE);
135
136     (void) wmove(win, bottom, x);
137     if (bottom_arrow) {
138         wattrset(win, merge_colors(darrow_attr, attr));
139         (void) add_acs(win, ACS_DARROW);
140         (void) waddstr(win, "(+)");
141     } else {
142         wattrset(win, borderattr);
143         (void) whline(win, dlg_boxchar(ACS_HLINE), ON_LEFT);
144     }
145     mouse_mkbutton(bottom, x - 1, 6, KEY_NPAGE);
146
147     (void) wmove(win, cur_y, cur_x);
148     wrefresh(win);
149
150     wattrset(win, save);
151 }
152
153 void
154 dlg_draw_scrollbar(WINDOW *win,
155                    long first_data,
156                    long this_data,
157                    long next_data,
158                    long total_data,
159                    int left,
160                    int right,
161                    int top,
162                    int bottom,
163                    chtype attr,
164                    chtype borderattr)
165 {
166     char buffer[80];
167     int percent;
168     int len;
169     int oldy, oldx, maxy, maxx;
170
171     chtype save = dlg_get_attrs(win);
172     int top_arrow = (first_data != 0);
173     int bottom_arrow = (next_data < total_data);
174
175     getyx(win, oldy, oldx);
176     getmaxyx(win, maxy, maxx);
177
178     dlg_draw_helpline(win, TRUE);
179     if (bottom_arrow || top_arrow || dialog_state.use_scrollbar) {
180         percent = (!total_data
181                    ? 100
182                    : (int) ((next_data * 100)
183                             / total_data));
184
185         if (percent < 0)
186             percent = 0;
187         else if (percent > 100)
188             percent = 100;
189
190         wattrset(win, position_indicator_attr);
191         (void) sprintf(buffer, "%d%%", percent);
192         (void) wmove(win, bottom, right - 7);
193         (void) waddstr(win, buffer);
194         if ((len = dlg_count_columns(buffer)) < 4) {
195             wattrset(win, border_attr);
196             whline(win, dlg_boxchar(ACS_HLINE), 4 - len);
197         }
198     }
199 #define BARSIZE(num) (int) (((all_high * (num)) + all_high - 1) / total_data)
200
201     if (dialog_state.use_scrollbar) {
202         int all_high = (bottom - top - 1);
203
204         if (total_data > 0 && all_high > 0) {
205             int bar_high;
206             int bar_y;
207
208             bar_high = BARSIZE(next_data - this_data);
209             if (bar_high <= 0)
210                 bar_high = 1;
211
212             if (bar_high < all_high) {
213                 wmove(win, top + 1, right);
214
215                 wattrset(win, save);
216                 wvline(win, ACS_VLINE | A_REVERSE, all_high);
217
218                 bar_y = BARSIZE(this_data);
219                 if (bar_y > all_high - bar_high)
220                     bar_y = all_high - bar_high;
221
222                 wmove(win, top + 1 + bar_y, right);
223
224                 wattrset(win, position_indicator_attr);
225                 wattron(win, A_REVERSE);
226                 wvline(win, ACS_BLOCK, bar_high);
227             }
228         }
229     }
230     dlg_draw_arrows2(win,
231                      top_arrow,
232                      bottom_arrow,
233                      left + ARROWS_COL,
234                      top,
235                      bottom,
236                      attr,
237                      borderattr);
238
239     wattrset(win, save);
240     wmove(win, oldy, oldx);
241 }
242
243 void
244 dlg_draw_arrows(WINDOW *win,
245                 int top_arrow,
246                 int bottom_arrow,
247                 int x,
248                 int top,
249                 int bottom)
250 {
251     dlg_draw_helpline(win, TRUE);
252     dlg_draw_arrows2(win,
253                      top_arrow,
254                      bottom_arrow,
255                      x,
256                      top,
257                      bottom,
258                      menubox_attr,
259                      menubox_border_attr);
260 }