diff --git a/src/wreadln.c b/src/wreadln.c
index 42703a0165ebc66566b7bca43625cf46b7c095a7..608141f6414e589d6ec74aca7c2610f33694feb1 100644 (file)
--- a/src/wreadln.c
+++ b/src/wreadln.c
#include "screen_utils.h"
#include "config.h"
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
WINDOW *const w;
/** the origin coordinates in the window */
- gint x, y;
+ unsigned x, y;
/** the screen width of the input field */
- gint width;
+ unsigned width;
/** is the input masked, i.e. characters displayed as '*'? */
const gboolean masked;
/** the byte position of the cursor */
- gint cursor;
+ size_t cursor;
/** the byte position displayed at the origin (for horizontal
scrolling) */
- gint start;
+ size_t start;
/** the current value */
- gchar *line;
+ gchar line[1024];
};
-/** max size allocated for a line */
-static const size_t wrln_max_line_size = 1024;
-
/** max items stored in the history list */
static const guint wrln_max_history_length = 32;
/* move the cursor one step to the right */
static inline void cursor_move_right(struct wreadln *wr)
{
- if (wr->cursor < (int)strlen(wr->line) &&
- wr->cursor < (int)wrln_max_line_size - 1) {
- ++wr->cursor;
- if (wr->cursor >= wr->width &&
- wr->start < wr->cursor - wr->width + 1)
- ++wr->start;
- }
+ if (wr->line[wr->cursor] == 0)
+ return;
+
+ ++wr->cursor;
+ if (wr->cursor >= (size_t)wr->width &&
+ wr->start < wr->cursor - wr->width + 1)
+ ++wr->start;
}
/* move the cursor one step to the left */
static inline void cursor_move_left(struct wreadln *wr)
{
- if (wr->cursor > 0) {
- if (wr->cursor == wr->start && wr->start > 0)
- --wr->start;
- --wr->cursor;
- }
+ if (wr->cursor == 0)
+ return;
+
+ if (wr->cursor == wr->start && wr->start > 0)
+ --wr->start;
+ --wr->cursor;
}
/* move the cursor to the end of the line */
doupdate();
}
+static void
+wreadln_insert_byte(struct wreadln *wr, gint key)
+{
+ size_t rest = strlen(wr->line + wr->cursor) + 1;
+ const size_t length = 1;
+
+ memmove(wr->line + wr->cursor + length,
+ wr->line + wr->cursor, rest);
+ wr->line[wr->cursor] = key;
+
+ cursor_move_right(wr);
+}
+
+static void
+wreadln_delete_char(struct wreadln *wr, size_t x)
+{
+ size_t i;
+
+ assert(x < strlen(wr->line));
+
+ for (i = x; wr->line[i] != 0; i++)
+ wr->line[i] = wr->line[i + 1];
+}
+
/* libcurses version */
static gchar *
_wreadln(WINDOW *w,
const gchar *prompt,
const gchar *initial_value,
- gint x1,
+ unsigned x1,
GList **history,
GCompletion *gcmp,
gboolean masked)
.start = 0,
};
GList *hlist = NULL, *hcurrent = NULL;
- gint key = 0, i;
+ gint key = 0;
+ size_t i;
- /* allocate a line buffer */
- wr.line = g_malloc0(wrln_max_line_size);
/* turn off echo */
noecho();
/* make shure the cursor is visible */
/* retrive y and x0 position */
getyx(w, wr.y, wr.x);
/* check the x1 value */
- if (x1 <= wr.x || x1 > COLS)
+ if (x1 <= wr.x || x1 > (unsigned)COLS)
x1 = COLS;
wr.width = x1 - wr.x;
/* clear input area */
if (history) {
/* append the a new line to our history list */
- *history = g_list_append(*history, g_malloc0(wrln_max_line_size));
+ *history = g_list_append(*history, g_malloc0(sizeof(wr.line)));
/* hlist points to the current item in the history list */
hlist = g_list_last(*history);
hcurrent = hlist;
if (history && hlist->prev) {
if (hlist == hcurrent)
/* save the current line */
- g_strlcpy(hlist->data, wr.line, wrln_max_line_size);
+ g_strlcpy(hlist->data, wr.line, sizeof(wr.line));
/* get previous line */
hlist = hlist->prev;
- g_strlcpy(wr.line, hlist->data, wrln_max_line_size);
+ g_strlcpy(wr.line, hlist->data, sizeof(wr.line));
}
cursor_move_to_eol(&wr);
drawline(&wr);
} else if (initial_value) {
/* copy the initial value to the line buffer */
- g_strlcpy(wr.line, initial_value, wrln_max_line_size);
+ g_strlcpy(wr.line, initial_value, sizeof(wr.line));
cursor_move_to_eol(&wr);
drawline(&wr);
}
/* check if key is a function key */
for (i = 0; i < 63; i++)
- if (key == KEY_F(i)) {
+ if (key == (int)KEY_F(i)) {
key = KEY_F(1);
i = 64;
}
wrln_completion_callback_data);
list = g_completion_complete(gcmp, wr.line, &prefix);
if (prefix) {
- g_strlcpy(wr.line, prefix, wrln_max_line_size);
+ g_strlcpy(wr.line, prefix, sizeof(wr.line));
cursor_move_to_eol(&wr);
g_free(prefix);
} else
case KEY_CTRL_G:
screen_bell();
- g_free(wr.line);
if (history) {
g_free(hcurrent->data);
hcurrent->data = NULL;
case 127:
case KEY_BCKSPC: /* handle backspace: copy all */
case KEY_BACKSPACE: /* chars starting from curpos */
- if (wr.cursor > 0) {/* - 1 from buf[n+1] to buf */
- for (i = wr.cursor - 1; wr.line[i] != 0; i++)
- wr.line[i] = wr.line[i + 1];
+ if (wr.cursor > 0) { /* - 1 from buf[n+1] to buf */
cursor_move_left(&wr);
+ wreadln_delete_char(&wr, wr.cursor);
}
break;
case KEY_DC: /* handle delete key. As above */
case KEY_CTRL_D:
- if (wr.cursor <= (gint)utf8_width(wr.line) - 1) {
- for (i = wr.cursor; wr.line[i] != 0; i++)
- wr.line[i] = wr.line[i + 1];
- }
+ if (wr.line[wr.cursor] != 0)
+ wreadln_delete_char(&wr, wr.cursor);
break;
case KEY_UP:
case KEY_CTRL_P:
if (hlist == hcurrent)
/* save the current line */
g_strlcpy(hlist->data, wr.line,
- wrln_max_line_size);
+ sizeof(wr.line));
/* get previous line */
hlist = hlist->prev;
g_strlcpy(wr.line, hlist->data,
- wrln_max_line_size);
+ sizeof(wr.line));
}
cursor_move_to_eol(&wr);
break;
/* get next line */
hlist = hlist->next;
g_strlcpy(wr.line, hlist->data,
- wrln_max_line_size);
+ sizeof(wr.line));
}
cursor_move_to_eol(&wr);
break;
/* ignore char */
break;
default:
- if (key >= 32) {
- if (strlen(wr.line + wr.cursor)) { /* if the cursor is */
- /* not at the last pos */
- gchar *tmp = NULL;
- gsize size = strlen(wr.line + wr.cursor) + 1;
-
- tmp = g_malloc0(size);
- g_strlcpy (tmp, wr.line + wr.cursor, size);
- wr.line[wr.cursor] = key;
- wr.line[wr.cursor + 1] = 0;
- g_strlcat(&wr.line[wr.cursor + 1], tmp, size);
- g_free(tmp);
- cursor_move_right(&wr);
- } else {
- wr.line[wr.cursor + 1] = 0;
- wr.line[wr.cursor] = key;
- cursor_move_right(&wr);
- }
- }
+ if (key >= 32)
+ wreadln_insert_byte(&wr, key);
}
drawline(&wr);
}
}
- return g_realloc(wr.line, strlen(wr.line) + 1);
+ return g_strdup(wr.line);
}
gchar *
wreadln(WINDOW *w,
const gchar *prompt,
const gchar *initial_value,
- gint x1,
+ unsigned x1,
GList **history,
GCompletion *gcmp)
{
wreadln_masked(WINDOW *w,
const gchar *prompt,
const gchar *initial_value,
- gint x1,
+ unsigned x1,
GList **history,
GCompletion *gcmp)
{