2 * Copyright (c)2004 Cat's Eye Technologies. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
16 * Neither the name of Cat's Eye Technologies nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
36 * $Id: curses_widget.c,v 1.12 2005/02/08 07:49:03 cpressey Exp $
44 #include "libaura/mem.h"
46 #include "curses_form.h"
47 #include "curses_widget.h"
48 #include "curses_bar.h"
49 #include "curses_util.h"
52 extern FILE *dfui_debug_file;
55 extern struct curses_bar *statusbar;
60 * Create a new curses_widget, outside of the context of any particular
63 struct curses_widget *
64 curses_widget_new(unsigned int x, unsigned int y,
65 unsigned int width, widget_t type,
66 const char *text, unsigned int size,
69 struct curses_widget *w;
71 AURA_MALLOC(w, curses_widget);
75 if (flags & CURSES_WIDGET_WIDEN) {
78 width = strlen(text) + 2;
81 width = strlen(text) + 4;
98 if (w->type == CURSES_TEXTBOX) {
100 w->text = aura_malloc(size, "w->text");
101 strcpy(w->text, text);
103 w->text = aura_strdup(text);
104 w->size = strlen(text) + 1;
105 /* size argument is ignored */
108 w->curpos = strlen(w->text);
124 * Free the memory allocated for a curses_widget. Note that this does
125 * NOT free any allocated memory at the widget's userdata pointer.
128 curses_widget_free(struct curses_widget *w)
130 if (w->tooltip != NULL)
133 AURA_FREE(w, curses_widget);
137 curses_widget_tooltip_set(struct curses_widget *w, const char *tooltip)
139 if (w->tooltip != NULL)
141 w->tooltip = aura_strdup(tooltip);
145 * Draw a curses_widget to the window of its associated curses_form.
146 * Note that this does not refresh the screen.
149 curses_widget_draw(struct curses_widget *w)
151 unsigned int wx, wy, x, len, i, charpos, cutoff, fchpos;
154 struct curses_form *cf = w->form;
156 wx = w->x + 1 - cf->x_offset;
157 wy = w->y + 1 - cf->y_offset;
160 * If the widget is outside the clipping rectangle of the
161 * form, don't draw it.
163 if (!curses_form_widget_is_visible(w))
166 wmove(cf->win, wy, wx);
168 curses_colors_set(cf->win, w == cf->widget_focus ?
169 CURSES_COLORS_FOCUS : CURSES_COLORS_CONTROL);
173 curses_colors_set(cf->win, CURSES_COLORS_LABEL); /* XXX conditional on... */
174 waddnstr(cf->win, w->text, w->width);
178 waddstr(cf->win, "[");
179 curses_colors_set(cf->win, CURSES_COLORS_TEXT); /* XXX focus ? */
181 len = strlen(w->text);
182 for (x = 0; x < w->width - 2; x++) {
184 waddch(cf->win, w->obscured ?
185 '*' : w->text[charpos]);
188 waddch(cf->win, ' ');
191 curses_colors_set(cf->win, w == cf->widget_focus ?
192 CURSES_COLORS_FOCUS : CURSES_COLORS_CONTROL);
193 waddstr(cf->win, "]");
195 * Position the cursor to where it's expected.
197 if (w->curpos - w->offset < w->width - 2) {
198 wmove(cf->win, w->y + 1 - cf->y_offset,
199 w->x + 2 - cf->x_offset + w->curpos - w->offset);
201 wmove(cf->win, w->y + 1 - cf->y_offset,
202 w->x + 2 - cf->x_offset + w->width - 2);
207 waddstr(cf->win, "< ");
208 waddnstr(cf->win, w->text, w->width - 4);
209 waddstr(cf->win, " >");
210 if (isprint(w->accel)) {
211 for (i = 0; w->text[i] != '\0'; i++) {
212 if (toupper(w->text[i]) == w->accel) {
213 wmove(cf->win, wy, wx + 2 + i);
214 curses_colors_set(cf->win, w == cf->widget_focus ?
215 CURSES_COLORS_ACCELFOCUS : CURSES_COLORS_ACCEL);
216 waddch(cf->win, w->text[i]);
223 case CURSES_PROGRESS:
224 waddstr(cf->win, "[");
225 snprintf(p, 5, "%3d%%", w->amount);
226 cutoff = (w->amount * (w->width - 2)) / 100;
227 fchpos = ((w->width - 2) / 2) - 2;
228 for (x = 0; x < w->width - 2; x++) {
230 curses_colors_set(cf->win, CURSES_COLORS_FOCUS);/* XXX status ? */
231 bar_char = monochrome ? '=' : ' ';
233 curses_colors_set(cf->win, CURSES_COLORS_CONTROL);
237 if (x >= fchpos && x <= fchpos + 3)
238 waddch(cf->win, p[x - fchpos]);
240 waddch(cf->win, bar_char);
242 waddstr(cf->win, "]");
245 case CURSES_CHECKBOX:
246 waddstr(cf->win, "[");
247 waddstr(cf->win, w->amount ? "X" : " ");
248 waddstr(cf->win, "]");
255 curses_widget_draw_tooltip(struct curses_widget *w)
257 if (w->tooltip != NULL)
258 curses_bar_set_text(statusbar, w->tooltip);
262 * Returns non-zero if the given widget can take control focus
263 * (i.e. if it is not a label, progress bar, or other inert element.)
266 curses_widget_can_take_focus(struct curses_widget *w)
268 if (w->type == CURSES_LABEL || w->type == CURSES_PROGRESS)
274 curses_widget_set_click_cb(struct curses_widget *w,
275 int (*callback)(struct curses_widget *))
277 w->click_cb = callback;
283 * -1 to indicate that the widget is not clickable.
284 * 0 to indicate that the widget clicked.
285 * 1 to indicate that the widget clicked and that its form should close.
288 curses_widget_click(struct curses_widget *w)
290 if ((w->type != CURSES_BUTTON && w->type != CURSES_TEXTBOX) ||
294 return(w->click_cb(w));
297 /*** TEXTBOX WIDGETS ***/
300 curses_textbox_advance_char(struct curses_widget *w)
302 if (w->text[w->curpos] != '\0') {
304 if ((w->curpos - w->offset) >= (w->width - 2))
306 curses_widget_draw(w);
307 curses_form_refresh(w->form);
315 curses_textbox_retreat_char(struct curses_widget *w)
319 if (w->curpos < w->offset)
321 curses_widget_draw(w);
322 curses_form_refresh(w->form);
330 curses_textbox_home(struct curses_widget *w)
334 curses_widget_draw(w);
335 curses_form_refresh(w->form);
340 curses_textbox_end(struct curses_widget *w)
342 w->curpos = strlen(w->text);
343 while ((w->curpos - w->offset) >= (w->width - 2)) {
346 curses_widget_draw(w);
347 curses_form_refresh(w->form);
352 curses_textbox_insert_char(struct curses_widget *w, char key)
359 len = strlen(w->text);
360 if (len == (w->size - 1))
363 w->text[len + 1] = '\0';
364 for (i = len; i > w->curpos; i--)
365 w->text[i] = w->text[i - 1];
366 w->text[w->curpos++] = key;
367 if ((w->curpos - w->offset) >= (w->width - 2))
369 curses_widget_draw(w);
370 curses_form_refresh(w->form);
375 curses_textbox_backspace_char(struct curses_widget *w)
382 len = strlen(w->text);
386 for (i = w->curpos; i <= len; i++)
387 w->text[i - 1] = w->text[i];
389 if (w->curpos < w->offset)
391 curses_widget_draw(w);
392 curses_form_refresh(w->form);
397 curses_textbox_delete_char(struct curses_widget *w)
404 len = strlen(w->text);
405 if (w->curpos == len)
408 for (i = w->curpos + 1; i <= len; i++)
409 w->text[i - 1] = w->text[i];
410 curses_widget_draw(w);
411 curses_form_refresh(w->form);
416 curses_textbox_set_text(struct curses_widget *w, const char *text)
418 strlcpy(w->text, text, w->size);
419 w->curpos = strlen(w->text);
420 curses_widget_draw(w);
421 curses_form_refresh(w->form);
425 /*** CHECKBOX WIDGETS ***/
428 curses_checkbox_toggle(struct curses_widget *w)
432 w->amount = !w->amount;
433 curses_widget_draw(w);
434 curses_form_refresh(w->form);
438 /*** PROGRESS WIDGETS ***/
440 char spinny[5] = "/-\\|";
443 curses_progress_spin(struct curses_widget *w)
445 struct curses_form *cf = w->form;
448 if (w->type != CURSES_PROGRESS)
451 wx = w->x + 1 - cf->x_offset;
452 wy = w->y + 1 - cf->y_offset;
454 w->spin = (w->spin + 1) % 4;
455 curses_colors_set(cf->win, CURSES_COLORS_FOCUS);/* XXX status ? */
456 mvwaddch(cf->win, wy, wx + 1, spinny[w->spin]);