/* * select the focus with a mouse event */ static int wdg_dialog_mouse_move(struct wdg_object *wo, struct wdg_mouse_event *mouse) { WDG_WO_EXT(struct wdg_dialog, ww); size_t y = wdg_get_begin_y(wo); size_t x = wdg_get_begin_x(wo); size_t i, l, c; /* get the line of the message */ wdg_dialog_get_size(wo, &l, &c); /* not on the button line */ if (mouse->y != y + 2 + l - 1) return -WDG_ENOTHANDLED; /* calculate the length of the buttons */ for (i = 0; i < WDG_DIALOG_MAX_BUTTON; i++) if (ww->buttons[i].selected) c -= strlen(ww->buttons[i].label); /* buttons start here */ x += c / 2; for (i = 0; i < WDG_DIALOG_MAX_BUTTON; i++) { /* if the mouse is over a title */ if (mouse->x >= x && mouse->x < x + strlen(ww->buttons[i].label) ) { ww->focus_button = i; return WDG_ESUCCESS; } /* move the pointer */ x += strlen(ww->buttons[i].label); } return -WDG_ENOTHANDLED; }
/* * print a string in the window */ void wdg_scroll_print(wdg_t *wo, int color, char *fmt, ...) { WDG_WO_EXT(struct wdg_scroll, ww); size_t c = wdg_get_ncols(wo); size_t l = wdg_get_nlines(wo); size_t x = wdg_get_begin_x(wo); size_t y = wdg_get_begin_y(wo); va_list ap; WDG_DEBUG_MSG("wdg_scroll_print"); /* move to the bottom of the pad */ wdg_set_scroll(wo, ww->y_max - l + 1); wbkgdset(ww->sub, COLOR_PAIR(color)); /* print the message */ va_start(ap, fmt); vw_printw(ww->sub, fmt, ap); va_end(ap); wbkgdset(ww->sub, COLOR_PAIR(wo->window_color)); WDG_PAD_REFRESH(ww, c, l, x, y); }
/* * called by the messages dispatcher when the window is focused */ static int wdg_scroll_get_msg(struct wdg_object *wo, int key, struct wdg_mouse_event *mouse) { WDG_WO_EXT(struct wdg_scroll, ww); size_t c = wdg_get_ncols(wo); size_t l = wdg_get_nlines(wo); size_t x = wdg_get_begin_x(wo); size_t y = wdg_get_begin_y(wo); /* handle the message */ switch (key) { case KEY_MOUSE: /* is the mouse event within our edges ? */ if (wenclose(ww->win, mouse->y, mouse->x)) { /* get the focus only if it was not focused */ if (!(wo->flags & WDG_OBJ_FOCUSED)) wdg_set_focus(wo); if (mouse->x == x + c - 1 && (mouse->y >= y + 1 && mouse->y <= y + l - 1)) { wdg_mouse_scroll(wo, mouse->y); WDG_PAD_REFRESH(ww, c, l, x, y); wnoutrefresh(ww->win); } } else return -WDG_ENOTHANDLED; break; /* handle scrolling of the pad */ case KEY_UP: wdg_set_scroll(wo, ww->y_scroll - 1); WDG_PAD_REFRESH(ww, c, l, x, y); wnoutrefresh(ww->win); break; case KEY_DOWN: wdg_set_scroll(wo, ww->y_scroll + 1); WDG_PAD_REFRESH(ww, c, l, x, y); wnoutrefresh(ww->win); break; case KEY_NPAGE: wdg_set_scroll(wo, ww->y_scroll + (l - 2)); WDG_PAD_REFRESH(ww, c, l, x, y); wnoutrefresh(ww->win); break; case KEY_PPAGE: wdg_set_scroll(wo, ww->y_scroll - (l - 2)); WDG_PAD_REFRESH(ww, c, l, x, y); wnoutrefresh(ww->win); break; /* message not handled */ default: return -WDG_ENOTHANDLED; break; } return WDG_ESUCCESS; }
/* * erase the subwindow */ void wdg_scroll_erase(wdg_t *wo) { WDG_WO_EXT(struct wdg_scroll, ww); size_t c = wdg_get_ncols(wo); size_t l = wdg_get_nlines(wo); size_t x = wdg_get_begin_x(wo); size_t y = wdg_get_begin_y(wo); werase(ww->sub); WDG_PAD_REFRESH(ww, c, l, x, y); }
/* * jump to a scroll position with the mouse */ static void wdg_mouse_scroll(struct wdg_object *wo, int s) { WDG_WO_EXT(struct wdg_scroll, ww); size_t l = wdg_get_nlines(wo); size_t y = wdg_get_begin_y(wo); size_t base; /* calculate the relative displacement */ base = s - y - 1; /* special case for top and bottom */ if (base == 0) s = 0; else if (base == l - 3) s = ww->y_max - l + 1; /* else calulate the proportion */ else s = base * ww->y_max / (l - 2); /* set the scroller */ wdg_set_scroll(wo, s); }
/* * create the internal form */ static void wdg_input_form_create(struct wdg_object *wo) { WDG_WO_EXT(struct wdg_input_handle, ww); int mrows, mcols; size_t c = wdg_get_ncols(wo); size_t x = wdg_get_begin_x(wo); size_t y = wdg_get_begin_y(wo); /* the form is already posted */ if (ww->form) return; /* create the form */ ww->form = new_form(ww->fields); /* get the geometry to make a window */ scale_form(ww->form, &mrows, &mcols); /* create the window for the form */ ww->fwin = newwin(mrows, MAX(mcols, (int)c - 4), y + 1, x + 2); /* set the color */ wbkgd(ww->fwin, COLOR_PAIR(wo->window_color)); keypad(ww->fwin, TRUE); /* associate with the form */ set_form_win(ww->form, ww->fwin); /* the subwin for the form */ set_form_sub(ww->form, derwin(ww->fwin, mrows + 1, mcols, 1, 1)); /* make the active field in reverse mode */ set_field_back(current_field(ww->form), A_REVERSE); /* display the form */ post_form(ww->form); wnoutrefresh(ww->fwin); }
/* * create the internal menu for the files */ static void wdg_file_menu_create(struct wdg_object *wo) { WDG_WO_EXT(struct wdg_file_handle, ww); int mrows, mcols; int i; size_t c = wdg_get_ncols(wo); size_t x = wdg_get_begin_x(wo); size_t y = wdg_get_begin_y(wo); struct stat buf; /* the menu is already posted */ if (ww->nitems) return; WDG_DEBUG_MSG("wdg_file_menu_create"); /* get the working directory */ getcwd(ww->curpath, PATH_MAX); /* scan the directory */ ww->nlist = scandir(".", &ww->namelist, 0, alphasort); /* on error display the message in the box */ if (ww->nlist <= 0) { ww->nitems = 2; WDG_SAFE_REALLOC(ww->items, ww->nitems * sizeof(ITEM *)); ww->items[ww->nitems - 2] = new_item("/", "root"); ww->items[ww->nitems - 1] = new_item("Cannot open the directory", ""); item_opts_off(ww->items[ww->nitems - 1], O_SELECTABLE); } else { /* for each directory in the directory */ for (i = 0; i < ww->nlist; i++) { /* * transform the current dir into the root. * useful to exit from a path whose parent is not readable */ if (!strcmp(ww->namelist[i]->d_name, ".")) { strncpy(ww->namelist[i]->d_name, "/", 1); ww->nitems++; WDG_SAFE_REALLOC(ww->items, ww->nitems * sizeof(ITEM *)); ww->items[ww->nitems - 1] = new_item(ww->namelist[i]->d_name, "root"); continue; } /* get the file properties */ stat(ww->namelist[i]->d_name, &buf); if (S_ISDIR(buf.st_mode)) { ww->nitems++; WDG_SAFE_REALLOC(ww->items, ww->nitems * sizeof(ITEM *)); ww->items[ww->nitems - 1] = new_item(ww->namelist[i]->d_name, "[...]"); } // if not readable //item_opts_off(ww->items[ww->nitems - 1], O_SELECTABLE); } /* and now add the files */ for (i = 0; i < ww->nlist; i++) { /* get the file properties */ stat(ww->namelist[i]->d_name, &buf); if (!S_ISDIR(buf.st_mode)) { ww->nitems++; WDG_SAFE_REALLOC(ww->items, ww->nitems * sizeof(ITEM *)); ww->items[ww->nitems - 1] = new_item(ww->namelist[i]->d_name, ""); } } } /* null terminate the array */ WDG_SAFE_REALLOC(ww->items, (ww->nitems + 1) * sizeof(ITEM *)); ww->items[ww->nitems] = NULL; /* create the menu */ ww->m = new_menu(ww->items); /* set the dimensions */ set_menu_format(ww->m, ww->y - 2, 1); set_menu_spacing(ww->m, 2, 0, 0); /* get the geometry to make a window */ scale_menu(ww->m, &mrows, &mcols); /* * if the menu is larger than the main window * adapt to the new dimensions */ if (mcols > (int)c - 4) { ww->x = mcols + 4; wdg_file_redraw(wo); return; } /* create the window for the menu */ ww->mwin = newwin(mrows, MAX(mcols, (int)c - 4), y + 1, x + 2); /* set the color */ wbkgd(ww->mwin, COLOR_PAIR(wo->window_color)); keypad(ww->mwin, TRUE); /* associate with the menu */ set_menu_win(ww->m, ww->mwin); /* the subwin for the menu */ set_menu_sub(ww->m, derwin(ww->mwin, mrows + 1, mcols, 1, 1)); /* menu attributes */ set_menu_mark(ww->m, ""); set_menu_grey(ww->m, COLOR_PAIR(wo->window_color)); set_menu_back(ww->m, COLOR_PAIR(wo->window_color)); set_menu_fore(ww->m, COLOR_PAIR(wo->window_color) | A_REVERSE | A_BOLD); /* display the menu */ post_menu(ww->m); wnoutrefresh(ww->mwin); }
/* * called to redraw the file dialog */ static int wdg_file_redraw(struct wdg_object *wo) { WDG_WO_EXT(struct wdg_file_handle, ww); size_t c, l, x, y; WDG_DEBUG_MSG("wdg_file_redraw"); /* default dimentions */ wo->x1 = (current_screen.cols - ww->x) / 2; wo->y1 = (current_screen.lines - ww->y) / 2; wo->x2 = -wo->x1; wo->y2 = -wo->y1; c = wdg_get_ncols(wo); l = wdg_get_nlines(wo); x = wdg_get_begin_x(wo); y = wdg_get_begin_y(wo); /* deal with rouding */ if (l != ww->y) l = ww->y; if (c != ww->x) c = ww->x; /* the window already exist */ if (ww->win) { /* erase the border */ wbkgd(ww->win, COLOR_PAIR(wo->screen_color)); werase(ww->win); /* destroy the file list */ wdg_file_menu_destroy(wo); touchwin(ww->win); wnoutrefresh(ww->win); /* resize the window and draw the new border */ mvwin(ww->win, y, x); wresize(ww->win, l, c); wbkgd(ww->win, COLOR_PAIR(wo->window_color)); werase(ww->win); /* create the file list */ wdg_file_menu_create(wo); touchwin(ww->win); wdg_file_borders(wo); /* the first time we have to allocate the window */ } else { /* create the menu window (fixed dimensions) */ if ((ww->win = newwin(l, c, y, x)) == NULL) return -WDG_E_FATAL; /* create the file list */ wdg_file_menu_create(wo); /* set the window color */ wbkgd(ww->win, COLOR_PAIR(wo->window_color)); redrawwin(ww->win); /* draw the titles */ wdg_file_borders(wo); /* no scrolling */ scrollok(ww->win, FALSE); } /* refresh the window */ touchwin(ww->win); wnoutrefresh(ww->win); touchwin(ww->mwin); wnoutrefresh(ww->mwin); wo->flags |= WDG_OBJ_VISIBLE; return WDG_E_SUCCESS; }
/* * called to redraw a window */ static int wdg_scroll_redraw(struct wdg_object *wo) { WDG_WO_EXT(struct wdg_scroll, ww); size_t c = wdg_get_ncols(wo); size_t l = wdg_get_nlines(wo); size_t x = wdg_get_begin_x(wo); size_t y = wdg_get_begin_y(wo); WDG_DEBUG_MSG("wdg_scroll_redraw"); /* the window already exist */ if (ww->win) { /* erase the border */ wbkgd(ww->win, COLOR_PAIR(wo->screen_color)); werase(ww->win); touchwin(ww->win); wnoutrefresh(ww->win); /* resize the window and draw the new border */ mvwin(ww->win, y, x); wresize(ww->win, l, c); wdg_scroll_border(wo); /* set the window color */ wbkgd(ww->sub, COLOR_PAIR(wo->window_color)); touchwin(ww->sub); /* the pad is resized only orizzontally. * the vertical dimension can be larger than the screen */ wdg_scroll_set_lines(wo, ww->y_max); /* refresh it */ WDG_PAD_REFRESH(ww, c, l, x, y); /* the first time we have to allocate the window */ } else { /* a default value waiting for wdg_scroll_set_lines() */ ww->y_max = l * 5; /* create the outher window */ if ((ww->win = newwin(l, c, y, x)) == NULL) return -WDG_EFATAL; /* draw the borders */ wdg_scroll_border(wo); /* initialize the pointer */ wdg_set_scroll(wo, ww->y_max - l + 1); /* create the inner (actual) window */ if ((ww->sub = newpad(ww->y_max, c - 2)) == NULL) return -WDG_EFATAL; /* set the window color */ wbkgd(ww->sub, COLOR_PAIR(wo->window_color)); touchwin(ww->sub); /* move to the bottom of the pad */ wmove(ww->sub, ww->y_scroll + 1, 0); /* permit scroll in the pad */ scrollok(ww->sub, TRUE); } /* refresh the window */ touchwin(ww->sub); wnoutrefresh(ww->win); WDG_PAD_REFRESH(ww, c, l, x, y); wo->flags |= WDG_OBJ_VISIBLE; return WDG_ESUCCESS; }
/* * called to redraw a window */ static int wdg_window_redraw(struct wdg_object *wo) { WDG_WO_EXT(struct wdg_window, ww); size_t c = wdg_get_ncols(wo); size_t l = wdg_get_nlines(wo); size_t x = wdg_get_begin_x(wo); size_t y = wdg_get_begin_y(wo); WDG_DEBUG_MSG("wdg_window_redraw"); /* the window already exist */ if (ww->win) { /* erase the border */ wbkgd(ww->win, COLOR_PAIR(wo->screen_color)); werase(ww->win); touchwin(ww->win); wnoutrefresh(ww->win); /* resize the window and draw the new border */ mvwin(ww->win, y, x); wresize(ww->win, l, c); wdg_window_border(wo); /* resize the actual window and touch it */ mvwin(ww->sub, y + 1, x + 1); wresize(ww->sub, l - 2, c - 2); /* set the window color */ wbkgd(ww->sub, COLOR_PAIR(wo->window_color)); /* the first time we have to allocate the window */ } else { /* create the outher window */ if ((ww->win = newwin(l, c, y, x)) == NULL) return -WDG_EFATAL; /* draw the borders */ wdg_window_border(wo); /* create the inner (actual) window */ if ((ww->sub = newwin(l - 2, c - 2, y + 1, x + 1)) == NULL) return -WDG_EFATAL; /* set the window color */ wbkgd(ww->sub, COLOR_PAIR(wo->window_color)); werase(ww->sub); redrawwin(ww->sub); /* initialize the pointer */ wmove(ww->sub, 0, 0); scrollok(ww->sub, TRUE); } /* refresh the window */ redrawwin(ww->sub); redrawwin(ww->win); wnoutrefresh(ww->win); wnoutrefresh(ww->sub); wo->flags |= WDG_OBJ_VISIBLE; return WDG_ESUCCESS; }
/* * called to redraw a window */ static int wdg_dialog_redraw(struct wdg_object *wo) { WDG_WO_EXT(struct wdg_dialog, ww); size_t c, l, x, y; size_t lines, cols; WDG_DEBUG_MSG("wdg_dialog_redraw"); /* calculate the dimension and position */ wdg_dialog_get_size(wo, &lines, &cols); /* center on the screen, but not outside the edges */ if (cols + 4 >= current_screen.cols) wo->x1 = 0; else wo->x1 = (current_screen.cols - (cols + 4)) / 2; wo->y1 = (current_screen.lines - (lines + 4)) / 2; wo->x2 = -wo->x1; wo->y2 = -wo->y1; /* get the cohorditates as usual */ c = wdg_get_ncols(wo); l = wdg_get_nlines(wo); x = wdg_get_begin_x(wo); y = wdg_get_begin_y(wo); /* deal with rouding */ if (l != lines + 4) l = lines + 4; if (c != cols + 4) c = cols + 4; /* the window already exist */ if (ww->win) { /* erase the border */ wbkgd(ww->win, COLOR_PAIR(wo->screen_color)); werase(ww->win); touchwin(ww->win); wnoutrefresh(ww->win); /* resize the window and draw the new border */ mvwin(ww->win, y, x); wresize(ww->win, l, c); wdg_dialog_border(wo); wdg_dialog_buttons(wo); /* resize the actual window and touch it */ mvwin(ww->sub, y + 2, x + 2); wresize(ww->sub, l - 4, c - 4); /* set the window color */ wbkgdset(ww->sub, COLOR_PAIR(wo->window_color)); /* the first time we have to allocate the window */ } else { /* create the outher window */ if ((ww->win = newwin(l, c, y, x)) == NULL) return -WDG_EFATAL; /* draw the borders */ wdg_dialog_border(wo); wdg_dialog_buttons(wo); /* create the inner (actual) window */ if ((ww->sub = newwin(l - 4, c - 4, y + 2, x + 2)) == NULL) return -WDG_EFATAL; /* set the window color */ wbkgdset(ww->sub, COLOR_PAIR(wo->window_color)); werase(ww->sub); redrawwin(ww->sub); } /* print the message text */ wmove(ww->sub, 0, 0); wprintw(ww->sub, ww->text); /* refresh the window */ redrawwin(ww->sub); redrawwin(ww->win); wnoutrefresh(ww->win); wnoutrefresh(ww->sub); wo->flags |= WDG_OBJ_VISIBLE; return WDG_ESUCCESS; }
/* * called to redraw a window */ static int wdg_percentage_redraw(struct wdg_object *wo) { WDG_WO_EXT(struct wdg_percentage, ww); size_t c, l, x, y; size_t cols; /* calculate the dimension and position */ cols = strlen(wo->title) + 2; /* set the minimum */ if (cols < 45) cols = 45; /* center on the screen, but not outside the edges */ if (cols + 4 >= current_screen.cols) wo->x1 = 0; else wo->x1 = (current_screen.cols - (cols + 4)) / 2; wo->y1 = (current_screen.lines - 7) / 2; wo->x2 = -wo->x1; wo->y2 = -wo->y1; c = wdg_get_ncols(wo); l = wdg_get_nlines(wo); x = wdg_get_begin_x(wo); y = wdg_get_begin_y(wo); /* the window already exist */ if (ww->win) { /* erase the border */ wbkgd(ww->win, COLOR_PAIR(wo->screen_color)); werase(ww->win); touchwin(ww->win); wnoutrefresh(ww->win); /* resize the window and draw the new border */ mvwin(ww->win, y, x); wresize(ww->win, l, c); wdg_percentage_border(wo); /* resize the actual window and touch it */ mvwin(ww->sub, y + 1, x + 1); wresize(ww->sub, l - 2, c - 2); /* set the window color */ wbkgdset(ww->sub, COLOR_PAIR(wo->window_color)); /* the first time we have to allocate the window */ } else { /* create the outher window */ if ((ww->win = newwin(l, c, y, x)) == NULL) return -WDG_E_FATAL; /* draw the borders */ wdg_percentage_border(wo); /* create the inner (actual) window */ if ((ww->sub = newwin(l - 2, c - 2, y + 1, x + 1)) == NULL) return -WDG_E_FATAL; /* set the window color */ wbkgdset(ww->sub, COLOR_PAIR(wo->window_color)); werase(ww->sub); redrawwin(ww->sub); /* initialize the pointer */ wmove(ww->sub, 0, 0); scrollok(ww->sub, TRUE); } /* refresh the window */ redrawwin(ww->sub); redrawwin(ww->win); wnoutrefresh(ww->win); wnoutrefresh(ww->sub); wo->flags |= WDG_OBJ_VISIBLE; return WDG_E_SUCCESS; }