diff options
Diffstat (limited to 'src/fe-text/gui-entry.c')
-rw-r--r-- | src/fe-text/gui-entry.c | 367 |
1 files changed, 227 insertions, 140 deletions
diff --git a/src/fe-text/gui-entry.c b/src/fe-text/gui-entry.c index 0cdfa719..84a7cd7a 100644 --- a/src/fe-text/gui-entry.c +++ b/src/fe-text/gui-entry.c @@ -21,43 +21,65 @@ #include "module.h" #include "formats.h" +#include "gui-entry.h" #include "gui-printtext.h" #include "screen.h" -static GString *entry; -static int promptlen, permanent_prompt, pos, scrstart, scrpos; -static int prompt_hidden; -static char *prompt; +GUI_ENTRY_REC *active_entry; -static void entry_screenpos(void) +GUI_ENTRY_REC *gui_entry_create(int xpos, int ypos, int width) { - if (pos-scrstart < screen_width-2-promptlen && pos-scrstart > 0) { - scrpos = pos-scrstart; - return; - } + GUI_ENTRY_REC *rec; + + rec = g_new0(GUI_ENTRY_REC, 1); + rec->xpos = xpos; + rec->ypos = ypos; + rec->width = width; + rec->text = g_string_new(NULL); + return rec; +} + +void gui_entry_destroy(GUI_ENTRY_REC *entry) +{ + g_return_if_fail(entry != NULL); + + g_free_not_null(entry->prompt); + g_string_free(entry->text, TRUE); + g_free(entry); +} - if (pos < screen_width-1-promptlen) { - scrstart = 0; - scrpos = pos; +/* Fixes the cursor position in screen */ +static void gui_entry_fix_cursor(GUI_ENTRY_REC *entry) +{ + if (entry->pos - entry->scrstart < entry->width-2 - entry->promptlen && + entry->pos - entry->scrstart > 0) { + entry->scrpos = entry->pos - entry->scrstart; + } else if (entry->pos < entry->width-1 - entry->promptlen) { + entry->scrstart = 0; + entry->scrpos = entry->pos; } else { - scrpos = (screen_width-promptlen)*2/3; - scrstart = pos-scrpos; + entry->scrpos = (entry->width - entry->promptlen)*2/3; + entry->scrstart = entry->pos - entry->scrpos; } } -static void entry_update(void) +static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos) { char *p; - int n, len; + int xpos, end_xpos; - len = entry->len-scrstart > screen_width-1-promptlen ? - screen_width-1-promptlen : entry->len-scrstart; + xpos = entry->xpos + entry->promptlen + pos; + end_xpos = entry->xpos + entry->width; + if (xpos > end_xpos) + return; screen_set_color(screen_root, 0); - screen_move(screen_root, promptlen, screen_height-1); + screen_move(screen_root, xpos, entry->ypos); - for (p = entry->str+scrstart, n = 0; n < len; n++, p++) { - if (prompt_hidden) + p = entry->scrstart + pos >= entry->text->len ? "" : + entry->text->str + entry->scrstart + pos; + for (; *p != '\0' && xpos < end_xpos; p++, xpos++) { + if (entry->hidden) screen_addch(screen_root, ' '); else if ((unsigned char) *p >= 32) screen_addch(screen_root, (unsigned char) *p); @@ -67,234 +89,299 @@ static void entry_update(void) screen_set_color(screen_root, 0); } } - screen_clrtoeol(screen_root); - screen_move_cursor(scrpos+promptlen, screen_height-1); + /* clear the rest of the input line */ + if (entry->xpos + entry->width == screen_width) + screen_clrtoeol(screen_root); + else { + while (xpos < end_xpos) { + screen_addch(screen_root, ' '); + xpos++; + } + } + + screen_move_cursor(entry->xpos + entry->scrpos + entry->promptlen, + entry->ypos); screen_refresh(NULL); } -void gui_entry_set_prompt(const char *str) +static void gui_entry_draw(GUI_ENTRY_REC *entry) { - if (str != NULL) { - if (permanent_prompt) return; + gui_entry_draw_from(entry, 0); +} - g_free_not_null(prompt); - prompt = g_strdup(str); - promptlen = format_get_length(prompt); +void gui_entry_move(GUI_ENTRY_REC *entry, int xpos, int ypos, int width) +{ + int old_width; + + g_return_if_fail(entry != NULL); + + if (entry->xpos != xpos || entry->ypos != ypos) { + /* position in screen changed - needs a full redraw */ + entry->xpos = xpos; + entry->ypos = ypos; + entry->width = width; + gui_entry_redraw(entry); + return; } - if (prompt != NULL) - gui_printtext(0, screen_height-1, prompt); + if (entry->width == width) + return; /* no changes */ - entry_screenpos(); - entry_update(); + if (width > entry->width) { + /* input line grew - need to draw text at the end */ + old_width = width; + entry->width = width; + gui_entry_draw_from(entry, old_width); + } else { + /* input line shrinked - make sure the cursor + is inside the input line */ + if (entry->pos - entry->scrstart > + entry->width-2 - entry->promptlen) { + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); + } + } } -void gui_entry_set_perm_prompt(const char *str) +void gui_entry_set_active(GUI_ENTRY_REC *entry) { - g_return_if_fail(str != NULL); + active_entry = entry; - g_free_not_null(prompt); - prompt = g_strdup(str); - promptlen = format_get_length(prompt); - - permanent_prompt = TRUE; - gui_entry_set_prompt(NULL); + screen_move_cursor(entry->xpos + entry->scrpos + entry->promptlen, + entry->ypos); + screen_refresh(NULL); } -void gui_entry_set_hidden(int hidden) +void gui_entry_set_prompt(GUI_ENTRY_REC *entry, const char *str) { - prompt_hidden = hidden; + int oldlen; + + g_return_if_fail(entry != NULL); + + oldlen = entry->promptlen; + if (str != NULL) { + g_free_not_null(entry->prompt); + entry->prompt = g_strdup(str); + entry->promptlen = format_get_length(str); + } + + if (entry->prompt != NULL) + gui_printtext(entry->xpos, entry->ypos, entry->prompt); + + if (entry->promptlen != oldlen) { + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); + } } -void gui_entry_remove_perm_prompt(void) +void gui_entry_set_hidden(GUI_ENTRY_REC *entry, int hidden) { - permanent_prompt = FALSE; + g_return_if_fail(entry != NULL); + + entry->hidden = hidden; } -void gui_entry_set_text(const char *str) +void gui_entry_set_text(GUI_ENTRY_REC *entry, const char *str) { + g_return_if_fail(entry != NULL); g_return_if_fail(str != NULL); - g_string_assign(entry, str); - pos = entry->len; + g_string_assign(entry->text, str); + entry->pos = entry->text->len; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -char *gui_entry_get_text(void) +char *gui_entry_get_text(GUI_ENTRY_REC *entry) { - return entry->str; + g_return_val_if_fail(entry != NULL, NULL); + + return entry->text->str; } -void gui_entry_insert_text(const char *str) +void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str) { + g_return_if_fail(entry != NULL); g_return_if_fail(str != NULL); - g_string_insert(entry, pos, str); - pos += strlen(str); + g_string_insert(entry->text, entry->pos, str); + entry->pos += strlen(str); - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_insert_char(char chr) +void gui_entry_insert_char(GUI_ENTRY_REC *entry, char chr) { - if (chr == 0) return; /* never insert NUL characters */ + g_return_if_fail(entry != NULL); + + if (chr == 0) + return; /* never insert NUL characters */ - g_string_insert_c(entry, pos, chr); - pos++; + g_string_insert_c(entry->text, entry->pos, chr); + entry->pos++; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_erase(int size) +void gui_entry_erase(GUI_ENTRY_REC *entry, int size) { - if (pos < size) return; + g_return_if_fail(entry != NULL); + + if (entry->pos < size) + return; #ifdef WANT_BIG5 - if (is_big5(entry->str[pos-2], entry->str[pos-1])) + if (is_big5(entry->text->str[entry->pos-2], + entry->text->str[entry->pos-1])) size++; #endif - pos -= size; - g_string_erase(entry, pos, size); + entry->pos -= size; + g_string_erase(entry->text, entry->pos, size); - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_erase_word(void) +void gui_entry_erase_word(GUI_ENTRY_REC *entry) { int to; - - if (pos == 0) return; - to = pos - 1; + g_return_if_fail(entry != NULL); + if (entry->pos == 0) + return; + + to = entry->pos - 1; - while (entry->str[to] == ' ' && to > 0) + while (entry->text->str[to] == ' ' && to > 0) to--; - while (entry->str[to] != ' ' && to > 0) + while (entry->text->str[to] != ' ' && to > 0) to--; - if (entry->str[to] == ' ' && to > 0) + if (entry->text->str[to] == ' ' && to > 0) to++; - g_string_erase(entry, to, pos - to); - pos = to; + g_string_erase(entry->text, to, entry->pos - to); + entry->pos = to; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_erase_next_word(void) +void gui_entry_erase_next_word(GUI_ENTRY_REC *entry) { - int to = pos; - - if (pos == entry->len) return; + int to; + + g_return_if_fail(entry != NULL); + if (entry->pos == entry->text->len) + return; - while (entry->str[to] == ' ' && to < entry->len) + to = entry->pos; + while (entry->text->str[to] == ' ' && to < entry->text->len) to++; - while (entry->str[to] != ' ' && to < entry->len) + while (entry->text->str[to] != ' ' && to < entry->text->len) to++; - g_string_erase(entry, pos, to - pos); + g_string_erase(entry->text, entry->pos, to - entry->pos); - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -int gui_entry_get_pos(void) +int gui_entry_get_pos(GUI_ENTRY_REC *entry) { - return pos; + g_return_val_if_fail(entry != NULL, 0); + + return entry->pos; } -void gui_entry_set_pos(int p) +void gui_entry_set_pos(GUI_ENTRY_REC *entry, int pos) { - if (p >= 0 && p <= entry->len) - pos = p; + g_return_if_fail(entry != NULL); + + if (pos >= 0 && pos <= entry->text->len) + entry->pos = pos; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_move_pos(int p) +void gui_entry_move_pos(GUI_ENTRY_REC *entry, int pos) { + g_return_if_fail(entry != NULL); + #ifdef WANT_BIG5 - if (p > 0 && is_big5 (entry->str[pos], entry->str[pos+1])) - p++; - else if (p < 0 && is_big5 (entry->str[pos-1], entry->str[pos])) - p--; + if (pos > 0 && is_big5(entry->text->str[entry->pos], + entry->text->str[entry->pos+1])) + pos++; + else if (pos < 0 && is_big5(entry->text->str[entry->pos-1], + entry->text->str[entry->pos])) + pos--; #endif - if (pos+p >= 0 && pos+p <= entry->len) - pos += p; + if (entry->pos+pos >= 0 && entry->pos+pos <= entry->text->len) + entry->pos += pos; - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -static void gui_entry_move_words_left(int count) +static void gui_entry_move_words_left(GUI_ENTRY_REC *entry, int count) { - if (pos == 0) return; + int pos; + pos = entry->pos; while (count > 0 && pos > 0) { - while (pos > 0 && entry->str[pos-1] == ' ') + while (pos > 0 && entry->text->str[pos-1] == ' ') pos--; - while (pos > 0 && entry->str[pos-1] != ' ') + while (pos > 0 && entry->text->str[pos-1] != ' ') pos--; count--; } + + entry->pos = pos; } -static void gui_entry_move_words_right(int count) +static void gui_entry_move_words_right(GUI_ENTRY_REC *entry, int count) { - if (pos == entry->len) return; + int pos; - while (count > 0 && pos < entry->len) { - while (pos < entry->len && entry->str[pos] != ' ') + pos = entry->pos; + while (count > 0 && pos < entry->text->len) { + while (pos < entry->text->len && entry->text->str[pos] != ' ') pos++; - while (pos < entry->len && entry->str[pos] == ' ') + while (pos < entry->text->len && entry->text->str[pos] == ' ') pos++; count--; } + + entry->pos = pos; } -void gui_entry_move_words(int count) +void gui_entry_move_words(GUI_ENTRY_REC *entry, int count) { + g_return_if_fail(entry != NULL); + if (count < 0) - gui_entry_move_words_left(-count); + gui_entry_move_words_left(entry, -count); else if (count > 0) - gui_entry_move_words_right(count); + gui_entry_move_words_right(entry, count); - entry_screenpos(); - entry_update(); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } -void gui_entry_redraw(void) +void gui_entry_redraw(GUI_ENTRY_REC *entry) { - gui_entry_set_prompt(NULL); + g_return_if_fail(entry != NULL); - entry_screenpos(); - entry_update(); -} - -void gui_entry_init(void) -{ - entry = g_string_new(NULL); - - pos = scrpos = 0; - prompt = NULL; promptlen = 0; - permanent_prompt = FALSE; - prompt_hidden = FALSE; -} - -void gui_entry_deinit(void) -{ - if (prompt != NULL) g_free(prompt); - g_string_free(entry, TRUE); + gui_entry_set_prompt(entry, NULL); + gui_entry_fix_cursor(entry); + gui_entry_draw(entry); } |