diff options
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 258 |
1 files changed, 100 insertions, 158 deletions
diff --git a/src/utils.c b/src/utils.c index a5adec1..bee5e55 100644 --- a/src/utils.c +++ b/src/utils.c @@ -228,77 +228,51 @@ print_in_middle (WINDOW *win, int starty, int startx, int width, char *string) custom_remove_attr (win, ATTR_HIGHEST); } -/* - * Draw the cursor at the correct position in string. - * As echoing is not set, we need to know the string we are working on to - * handle display correctly. - */ +/* Print the string at the desired position. */ static void -showcursor (WINDOW *win, int y, int pos, char *str, int l, int offset) +showstring (WINDOW *win, int x, int y, char *str, int len, int scroff, + int curpos) { - char *nc; - - nc = str + pos; - wmove (win, y, pos - offset); - (pos >= l) ? waddch (win, SPACE | A_REVERSE) : waddch (win, *nc | A_REVERSE); -} + char c = 0; -/* Print the string at the desired position. */ -static void -showstring (WINDOW *win, int y, int x, char *str, int len, int pos) -{ - const int rec = 30, border = 3; - const int max_col = col - border, max_len = max_col - rec; - int page, max_page, offset, c = 0; - char *orig; - - orig = str; - max_page = (len - rec) / max_len; - page = (pos - rec) / max_len; - offset = page * max_len; - str += offset; - mvwaddnstr (win, y, x, str, MIN (len, max_col)); + /* print string */ + mvwaddnstr (win, y, x, &str[scroff], -1); wclrtoeol (win); - if (page > 0 && page < max_page) - { - c = '*'; - } - else if (page > 0) - { - c = '<'; - } - else if (page < max_page) - { - c = '>'; - } - else - c = 0; + + /* print scrolling indicator */ + if (scroff > 0 && scroff < len - col) c = '*'; + else if (scroff > 0) c = '<'; + else if (scroff < len - col) c = '>'; mvwprintw (win, y, col - 1, "%c", c); - showcursor (win, y, pos, orig, len, offset); + + /* print cursor */ + wmove (win, y, curpos - scroff); + + if (curpos >= len) waddch (win, SPACE | A_REVERSE); + else waddch (win, str[curpos] | A_REVERSE); } /* Delete a character at the given position in string. */ static void del_char (int pos, char *str) { - int len; - str += pos; - len = strlen (str) + 1; - memmove (str, str + 1, len); + memmove (str, str + 1, strlen (str) + 1); } /* Add a character at the given position in string. */ -static char * -add_char (int pos, int ch, char *str) +static void +ins_char (int pos, int ch, char *str) { - int len; - str += pos; - len = strlen (str) + 1; - memmove (str + 1, str, len); + memmove (str + 1, str, strlen (str) + 1); *str = ch; - return (str += len); +} + +void +bell (void) +{ + printf ("\a"); } /* @@ -312,117 +286,85 @@ add_char (int pos, int ch, char *str) enum getstr getstring (WINDOW *win, char *str, int l, int x, int y) { - int ch, newpos, len = 0; - char *orig; + const int pgsize = col / 3; + + int len = strlen (str); + int curpos = len; + int scroff = 0; + int ch; - orig = str; custom_apply_attr (win, ATTR_HIGHEST); - for (; *str; ++str, ++len) - ; - newpos = x + len; - showstring (win, y, x, orig, len, newpos); - while ((ch = wgetch (win)) != '\n') - { - switch (ch) - { - case KEY_BACKSPACE: /* delete one character */ - case 330: - case 127: - case CTRL ('H'): - if (len > 0 && newpos > x) - { - --newpos; - --len; - if (newpos >= x + len) - --str; - else /* to be deleted inside string */ - del_char (newpos, orig); - } - break; - - case CTRL ('D'): /* delete next character */ - if (newpos != (x + len)) - { - --len; - if (newpos >= x + len) - --str; - else - del_char (newpos, orig); - } - else - printf ("\a"); - break; - - case CTRL ('W'): /* delete a word */ - while (len > 0 && newpos > x && *(orig + newpos - 1) == ' ') { - --newpos; - --len; - if (newpos >= x + len) - --str; - else - del_char (newpos, orig); - } - while (len > 0 && newpos > x && *(orig + newpos - 1) != ' ') { - --newpos; - --len; - if (newpos >= x + len) - --str; - else - del_char (newpos, orig); + for (;;) { + while (curpos < scroff) scroff -= pgsize; + while (curpos >= scroff + col - 1) scroff += pgsize; + + showstring (win, x, y, str, len, scroff, curpos); + wins_doupdate (); + + if ((ch = wgetch (win)) == '\n') break; + switch (ch) { + case KEY_BACKSPACE: /* delete one character */ + case 330: + case 127: + case CTRL ('H'): + if (curpos > 0) { + del_char ((--curpos), str); + len--; + } + else bell (); + break; + case CTRL ('D'): /* delete next character */ + if (curpos < len) { + del_char (curpos, str); + len--; + } + else bell (); + break; + case CTRL ('W'): /* delete a word */ + if (curpos > 0) { + while (curpos && str[curpos - 1] == ' ') { + del_char ((--curpos), str); + len--; + } + while (curpos && str[curpos - 1] != ' ') { + del_char ((--curpos), str); + len--; + } + } + else bell (); + break; + case CTRL ('K'): /* delete to end-of-line */ + str[curpos] = 0; + len = curpos; + break; + case CTRL ('A'): /* go to begginning of string */ + curpos = 0; + break; + case CTRL ('E'): /* go to end of string */ + curpos = len; + break; + case KEY_LEFT: /* move one char backward */ + case CTRL ('B'): + if (curpos > 0) curpos--; + break; + case KEY_RIGHT: /* move one char forward */ + case CTRL ('F'): + if (curpos < len) curpos++; + break; + case ESCAPE: /* cancel editing */ + return (GETSTRING_ESC); + break; + default: /* insert one character */ + if (len < l - 1) { + ins_char ((curpos++), ch, str); + len++; + } } - break; - - case CTRL ('K'): /* delete to end-of-line */ - str = orig + newpos; - *str = 0; - len -= (len - newpos); - break; - - case CTRL ('A'): /* go to begginning of string */ - newpos = x; - break; - - case CTRL ('E'): /* go to end of string */ - newpos = x + len; - break; - - case KEY_LEFT: /* move one char backward */ - case CTRL ('B'): - if (newpos > x) - newpos--; - break; - - case KEY_RIGHT: /* move one char forward */ - case CTRL ('F'): - if (newpos < len) - newpos++; - break; - - case ESCAPE: /* cancel editing */ - return (GETSTRING_ESC); - break; - - default: /* insert one character */ - if (len < l - 1) - { - if (newpos >= len) - { - str = orig + newpos; - *str++ = ch; - } - else // char is to be inserted inside string - str = add_char (newpos, ch, orig); - ++len; - ++newpos; - } + } - } - showstring (win, y, x, orig, len, newpos); - wins_doupdate (); - } - *str = 0; custom_remove_attr (win, ATTR_HIGHEST); + return (len == 0 ? GETSTRING_RET : GETSTRING_VALID); } |