#define FF_LIST(f) (((form_list_t *)f))
/* Local variables */
-static WINDOW *form_win;
-static int form_row;
-static int form_col;
+static form_t *form; // current form
+static WINDOW *win; // current window
+static int arow; // active row
+static int acol; // active row
-/* Helpeer functions */
-int label_width(const char *label)
+/* Helper functions */
+static int label_width(const char *label)
{
int len = 0;
for (int i = 0; label[i]; i++)
return len;
}
-void label_print(WINDOW *win, const char *label)
+static void label_print(const char *label)
{
for (int i = 0; label[i]; i++) {
if (label[i] == '_' && label[i+1])
- waddch(form_win, label[++i]
+ waddch(win, label[++i]
| A_UNDERLINE | A_BOLD);
else
- waddch(form_win, label[i]);
+ waddch(win, label[i]);
}
}
-int field_width(form_field_t *field)
+static int field_width(form_field_t *field)
{
// Calculate list width
int list_size = 0;
return width;
}
-void field_sizes(form_t *form, int *col_size)
+static void field_sizes(form_t *form, int *col_size)
{
// Do this by column, and right to left so that we can add
// in the extra space available for blank spaces.
}
}
-void field_draw(WINDOW *win, form_field_t *field, int width, int hover)
+static void field_draw(form_field_t *field, int width, int hover)
{
char **map = FF_LIST(field)->map;
int idx = FF_LIST(field)->idx;
wprintw(win, "%s", before);
switch (field->type) {
case FORM_LABEL:
- label_print(win, field->label);
+ label_print(field->label);
break;
case FORM_TEXT:
wprintw(win, "%-.*s",
if (hover) wattroff(win, A_REVERSE);
}
-int is_active(form_t *form, int r, int c)
+static int is_active(form_t *form, int r, int c)
{
- if (r == form_row && c == form_col)
- return 1;
- for (int i = c+1; i < form->cols && !form->fields[r][i]; i++)
- if (r == form_row && i == form_col)
+ for (int i = c; i >= 0; i--) {
+ if (r == arow && i == acol)
+ return 1;
+ if (form->fields[r][i])
+ break;
+ }
+ for (int i = c+1; i < form->cols; i++) {
+ if (form->fields[r][i])
+ break;
+ if (r == arow && i == acol)
return 1;
+ }
return 0;
}
-int can_active(form_t *form, int r, int c)
+static int can_active(form_t *form, int r, int c)
{
for (int i = c; i >= 0; i--) {
if (!form->fields[r][i])
continue;
- if (form->fields[r][i]->type != FORM_LABEL)
- return 1;
- else
+ if (form->fields[r][i]->type == FORM_LABEL)
return 0;
+ return 1;
}
return 0;
}
-void set_active(form_t *form, int ro, int co)
+static int set_active(form_t *form, int r, int c)
+{
+ if (can_active(form, r, c)) {
+ arow = r;
+ acol = c;
+ return 1;
+ }
+ return 0;
+}
+
+static void move_active(form_t *form, int ro, int co)
{
// Set first field
- if (ro==0 && co==0) {
+ if (ro==0 && co==0)
for (int r = 0; r < form->rows; r++)
- for (int c = 0; c < form->cols; c++) {
- if (can_active(form, r, c)) {
- form_row = r;
- form_col = c;
+ for (int c = 0; c < form->cols; c++)
+ if (set_active(form, r, c))
return;
- }
- }
- }
// Move up/down
if (ro) {
- for (int ri = form_row+ro; ri>=0 && ri<form->rows; ri+=ro) {
- if (can_active(form, ri, form_col)) {
- form_row = ri;
- return;
- }
+ for (int ri = arow+ro; ri>=0 && ri<form->rows; ri+=ro) {
+ if (is_active(form, ri, acol))
+ continue;
+ // Search for a row
+ for (int ci = acol; ci < form->cols; ci++)
+ if (set_active(form, ri, ci))
+ return;
+ for (int ci = acol; ci >= 0; ci--)
+ if (set_active(form, ri, ci))
+ return;
}
}
// Move left/right
if (co) {
- for (int ci = form_col+co; ci>=0 && ci<form->cols; ci+=co) {
- for (int ri = form_row; ri < form->rows; ri++)
- if (can_active(form, form_row, ci)) {
- form_row = ri;
- form_col = ci;
- return;
- }
- for (int ri = form_row; ri >= 0; ri--)
- if (can_active(form, form_row, ci)) {
- form_row = ri;
- form_col = ci;
- return;
- }
+ for (int ci = acol+co; ci>=0 && ci<form->cols; ci+=co) {
+ if (is_active(form, arow, ci))
+ continue;
+ // Simple move
+ if (set_active(form, arow, ci))
+ return;
}
}
}
-/* Initialize */
-void form_init(void)
+/* Form functions */
+void form_show(form_t *_form)
{
- form_win = newwin(LINES, COLS, 0, 0);
+ // Save form
+ form = _form;
}
-/* Resize */
-void form_resize(void)
+void form_draw(WINDOW *_win)
{
- mvwin(form_win, 0, 0);
- wresize(form_win, LINES, COLS);
-}
+ // Save window
+ win = _win;
-/* Run */
-int form_draw(form_t *form)
-{
- int col_size[form->cols];
+ // Validate everything
+ if (!win || !form)
+ return;
// Calculate column width
+ int col_size[form->cols];
field_sizes(form, col_size);
// Make sure we have an active field
- if (!can_active(form, form_row, form_col))
- set_active(form, 0, 0);
+ if (!can_active(form, arow, acol))
+ move_active(form, 0, 0);
// Display form
for (int r = 0; r < form->rows; r++) {
}
// Draw the field
if (field)
- field_draw(form_win, field, width,
- is_active(form, r, c));
+ field_draw(field, width, is_active(form, r, c));
else if (c == 0)
- wprintw(form_win, "%*s", width, "");
+ wprintw(win, "%*s", width, "");
}
- wprintw(form_win, "\n");
+ wprintw(win, "\n");
}
- return 0;
}
-int form_run(form_t *form, int key, mmask_t btn, int row, int col)
+int form_run(int key, mmask_t btn, int row, int col)
{
+ // Validate everything
+ if (!form)
+ return 0;
+
// Check movement keys
switch (key) {
- case 'h': set_active(form, 0, -1); goto redraw;
- case 'j': set_active(form, 1, 0); goto redraw;
- case 'k': set_active(form, -1, 0); goto redraw;
- case 'l': set_active(form, 0, 1); goto redraw;
+ case 'h': move_active(form, 0, -1); goto redraw;
+ case 'j': move_active(form, 1, 0); goto redraw;
+ case 'k': move_active(form, -1, 0); goto redraw;
+ case 'l': move_active(form, 0, 1); goto redraw;
}
// Handle mouse movement
for (int c = 0; c < form->cols; c++) {
if (pos < col && col < pos+col_size[c]) {
if (can_active(form, row, c)) {
- form_row = row;
- form_col = c;
+ arow = row;
+ acol = c;
goto redraw;
}
}
for (int c = 0; c < form->cols; c++)
if (form->fields[r][c] &&
form->fields[r][c]->hotkey == key) {
- form_row = r;
- form_col = c;
+ arow = r;
+ acol = c;
goto redraw;
}
return 0;
redraw:
- werase(form_win);
- form_draw(form);
- wrefresh(form_win);
+ werase(win);
+ form_draw(win);
+ wrefresh(win);
return 1;
}
mousemask(ALL_MOUSE_EVENTS, NULL);
/* Init */
- form_init();
+ win = newwin(LINES, COLS, 0, 0);
+ form_show(&edit);
/* Run */
while (1) {
continue;
switch (chr) {
case KEY_RESIZE:
- form_resize();
+ mvwin(win, 0, 0);
+ wresize(win, LINES, COLS);
refresh();
- werase(form_win);
- form_draw(&edit);
- wrefresh(form_win);
+ werase(win);
+ form_draw(win);
+ wrefresh(win);
continue;
case '\14': // Ctrl-L
clear();
case '\7': // Ctrl-G
refresh();
- werase(form_win);
- form_draw(&edit);
- wrefresh(form_win);
+ werase(win);
+ form_draw(win);
+ wrefresh(win);
continue;
}
- if (form_run(&edit, chr, btn.bstate, btn.y, btn.x))
+ if (form_run(chr, btn.bstate, btn.y, btn.x))
continue;
if (chr == ERR) // timeout
continue;