1
1

patches by Rostislav Beneš: mc-06-input

in input widget I made a lot of changes:
    1. rename some members in WInput to reflect more their functions
       (field_len -> field_width, ...)
    2. buffer for reading multibytes characters - charbuf, (taken from UTF-8
       patch)
    3. modified insert_char to accept mulstibytes characters, drawing changed
    4. works only with valid strings, str_fix_string used to assure that
       input->buffer is valid

changes in complete.c:
    - some iteration strings with ++/-- replaced with str_next_char,
    str_prev_char, where was needed. ++ was offset oriented, but str_next_char
    use directly referecne (char *), so result is not extra beatiful in every
     cases
    - other buffer for multibytes characters
    - complete only valid filenames
Этот коммит содержится в:
Slava Zanko 2008-12-29 00:52:45 +02:00
родитель 9450950fd4
Коммит 7f71be0d63
3 изменённых файлов: 340 добавлений и 198 удалений

Просмотреть файл

@ -41,6 +41,7 @@
#include "complete.h"
#include "main.h"
#include "key.h" /* XCTRL and ALT macros */
#include "strutil.h"
typedef char *CompletionFunction (char *, int);
@ -97,6 +98,8 @@ filename_completion_function (char *text, int state)
/* Now that we have some state, we can read the directory. */
while (directory && (entry = mc_readdir (directory))){
if (!str_is_valid_string (entry->d_name)) continue;
/* Special case for no filename.
All entries except "." and ".." match. */
if (!filename_len){
@ -273,20 +276,24 @@ static void fetch_hosts (const char *filename)
{
FILE *file = fopen (filename, "r");
char buffer[256], *name;
register int i, start;
char *start;
char *bi;
if (!file)
return;
while (fgets (buffer, 255, file) != NULL){
/* Skip to first character. */
for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++);
for (bi = buffer;
bi[0] != '\0' && str_isspace (bi);
str_next_char (&bi));
/* Ignore comments... */
if (buffer[i] == '#')
if (bi[0] == '#')
continue;
/* Handle $include. */
if (!strncmp (buffer + i, "$include ", 9)){
char *includefile = buffer + i + 9;
if (!strncmp (bi, "$include ", 9)){
char *includefile = bi + 9;
char *t;
/* Find start of filename. */
@ -295,8 +302,8 @@ static void fetch_hosts (const char *filename)
t = includefile;
/* Find end of filename. */
while (*t && !cr_whitespace (*t))
t++;
while (t[0] != '\0' && !str_isspace (t))
str_next_char (&t);
*t = '\0';
fetch_hosts (includefile);
@ -304,19 +311,22 @@ static void fetch_hosts (const char *filename)
}
/* Skip IP #s. */
while (buffer[i] && !cr_whitespace (buffer[i]))
i++;
while (bi[0] != '\0' && !str_isspace (bi))
str_next_char (&bi);
/* Get the host names separated by white space. */
while (buffer[i] && buffer[i] != '#'){
while (buffer[i] && cr_whitespace (buffer[i]))
i++;
if (buffer[i] == '#')
while (bi[0] != '\0' && bi[0] != '#'){
while (bi[0] != '\0' && str_isspace (bi))
str_next_char (&bi);
if (bi[0] == '#')
continue;
for (start = i; buffer[i] && !cr_whitespace (buffer[i]); i++);
if (i - start == 0)
continue;
name = g_strndup (buffer + start, i - start);
for (start = bi;
bi[0] != '\0' && !str_isspace (bi);
str_next_char (&bi));
if (bi - start == 0) continue;
name = g_strndup (start, bi - start);
{
char **host_p;
@ -566,19 +576,30 @@ completion_matches (char *text, CompletionFunction entry_function)
j = i + 1;
while (j < matches + 1)
{
register int c1, c2, si;
char *si, *sj;
char *ni, *nj;
for (si = 0;(c1 = match_list [i][si]) && (c2 = match_list [j][si]); si++)
if (c1 != c2) break;
for (si = match_list[i], sj = match_list[j];
si[0] && sj[0];) {
ni = str_get_next_char (si);
nj = str_get_next_char (sj);
if (!c1 && !match_list [j][si]){ /* Two equal strings */
if (ni - si != nj - sj) break;
if (strncmp (si, sj, ni - si) != 0) break;
si = ni;
sj = nj;
}
if (si[0] == '\0' && sj[0] == '\0'){ /* Two equal strings */
g_free (match_list [j]);
j++;
if (j > matches)
break;
continue; /* Look for a run of equal strings */
} else
if (low > si) low = si;
if (low > si - match_list[i]) low = si - match_list[i];
if (i + 1 != j) /* So there's some gap */
match_list [i + 1] = match_list [j];
i++; j++;
@ -598,7 +619,8 @@ completion_matches (char *text, CompletionFunction entry_function)
static int
check_is_cd (const char *text, int start, int flags)
{
const char *p, *q;
char *p, *q;
int test = 0;
if (flags & INPUT_COMPLETE_CD)
return 1;
@ -607,14 +629,18 @@ check_is_cd (const char *text, int start, int flags)
return 0;
/* Skip initial spaces */
p = text;
q = text + start;
while (p < q && *p && isspace ((unsigned char) *p))
p++;
p = (char*)text;
q = (char*)text + start;
while (p < q && p[0] != '\0' && str_isspace (p))
str_next_char (&p);
/* Check if the command is "cd" and the cursor is after it */
if (p[0] == 'c' && p[1] == 'd' && isspace ((unsigned char) p[2])
&& (p + 2 < q))
text+= p[0] == 'c';
str_next_char (&p);
text+= p[0] == 'd';
str_next_char (&p);
text+= str_isspace (p);
if (test == 3 && (p < q))
return 1;
return 0;
@ -624,44 +650,44 @@ check_is_cd (const char *text, int start, int flags)
static char **
try_complete (char *text, int *start, int *end, int flags)
{
int in_command_position = 0, i;
char *word, c;
int in_command_position = 0;
char *word;
char **matches = NULL;
const char *command_separator_chars = ";|&{(`";
char *p = NULL, *q = NULL, *r = NULL;
int is_cd = check_is_cd (text, *start, flags);
char *ti;
ignore_filenames = 0;
c = text [*end];
text [*end] = 0;
word = g_strdup (text + *start);
text [*end] = c;
word = g_strndup (text + *start, *end - *start);
/* Determine if this could be a command word. It is if it appears at
the start of the line (ignoring preceding whitespace), or if it
appears after a character that separates commands. And we have to
be in a INPUT_COMPLETE_COMMANDS flagged Input line. */
if (!is_cd && (flags & INPUT_COMPLETE_COMMANDS)){
i = *start - 1;
while (i > -1 && (text[i] == ' ' || text[i] == '\t'))
i--;
if (i < 0)
ti = str_get_prev_char (&text[*start]);
while (ti > text && (ti[0] == ' ' || ti[0] == '\t'))
str_prev_char (&ti);
if (ti <= text&& (ti[0] == ' ' || ti[0] == '\t'))
in_command_position++;
else if (strchr (command_separator_chars, text[i])){
else if (strchr (command_separator_chars, ti[0])){
register int this_char, prev_char;
in_command_position++;
if (i){
if (ti > text){
/* Handle the two character tokens `>&', `<&', and `>|'.
We are not in a command position after one of these. */
this_char = text[i];
prev_char = text[i - 1];
this_char = ti[0];
prev_char = str_get_prev_char (ti)[0];
if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
(this_char == '|' && prev_char == '>'))
in_command_position = 0;
else if (i > 0 && text [i-1] == '\\') /* Quoted */
else if (ti > text && str_get_prev_char (ti)[0] == '\\') /* Quoted */
in_command_position = 0;
}
}
@ -675,15 +701,15 @@ try_complete (char *text, int *start, int *end, int flags)
r = strrchr (word, '@');
if (q && q [1] == '(' && INPUT_COMPLETE_COMMANDS){
if (q > p)
p = q + 1;
p = str_get_next_char (q);
q = NULL;
}
/* Command substitution? */
if (p > q && p > r){
matches = completion_matches (p + 1, command_completion_function);
matches = completion_matches (str_get_next_char (p), command_completion_function);
if (matches)
*start += p + 1 - word;
*start += str_get_next_char (p) - word;
}
/* Variable name? */
@ -721,9 +747,9 @@ try_complete (char *text, int *start, int *end, int flags)
if (!matches && is_cd && *word != PATH_SEP && *word != '~'){
char *p, *q = text + *start;
for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); p++);
for (p = text; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p));
if (!strncmp (p, "cd", 2))
for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); p++);
for (p += 2; *p && p < q && (*p == ' ' || *p == '\t'); str_next_char (&p));
if (p == q){
char * const cdpath_ref = g_strdup (getenv ("CDPATH"));
char *cdpath = cdpath_ref;
@ -747,7 +773,7 @@ try_complete (char *text, int *start, int *end, int flags)
g_free (r);
}
*s = c;
cdpath = s + 1;
cdpath = str_get_next_char (s);
}
g_free (cdpath_ref);
}
@ -776,49 +802,57 @@ static WInput *input;
static int min_end;
static int start, end;
static int insert_text (WInput *in, char *text, ssize_t len)
static int insert_text (WInput *in, char *text, ssize_t size)
{
len = min (len, (ssize_t) strlen (text)) + start - end;
if (strlen (in->buffer) + len >= (size_t) in->current_max_len){
int buff_len = str_length (in->buffer);
size = min (size, (ssize_t) strlen (text)) + start - end;
if (strlen (in->buffer) + size >= (size_t) in->current_max_size){
/* Expand the buffer */
char *narea = g_realloc (in->buffer, in->current_max_len + len + in->field_len);
char *narea = g_realloc (in->buffer, in->current_max_size
+ size + in->field_width);
if (narea){
in->buffer = narea;
in->current_max_len += len + in->field_len;
in->current_max_size += size + in->field_width;
}
}
if (strlen (in->buffer)+1 < (size_t) in->current_max_len){
if (len > 0){
if (strlen (in->buffer)+1 < (size_t) in->current_max_size){
if (size > 0){
int i = strlen (&in->buffer [end]);
for (; i >= 0; i--)
in->buffer [end + len + i] = in->buffer [end + i];
} else if (len < 0){
char *p = in->buffer + end + len, *q = in->buffer + end;
in->buffer [end + size + i] = in->buffer [end + i];
} else if (size < 0){
char *p = in->buffer + end + size, *q = in->buffer + end;
while (*q)
*(p++) = *(q++);
*p = 0;
}
memcpy (in->buffer + start, text, len - start + end);
in->point += len;
memcpy (in->buffer + start, text, size - start + end);
in->point+= str_length (in->buffer) - buff_len;
update_input (in, 1);
end += len;
end+= size;
}
return len != 0;
return size != 0;
}
static cb_ret_t
query_callback (Dlg_head *h, dlg_msg_t msg, int parm)
{
static char buff[MB_LEN_MAX] = "";
static int bl = 0;
switch (msg) {
case DLG_KEY:
switch (parm) {
case KEY_LEFT:
case KEY_RIGHT:
bl = 0;
h->ret_value = 0;
dlg_stop (h);
return MSG_HANDLED;
case KEY_BACKSPACE:
bl = 0;
if (end == min_end) {
h->ret_value = 0;
dlg_stop (h);
@ -828,13 +862,13 @@ query_callback (Dlg_head *h, dlg_msg_t msg, int parm)
e1 = e = ((WListbox *) (h->current))->list;
do {
if (!strncmp
(input->buffer + start, e1->text,
end - start - 1)) {
listbox_select_entry ((WListbox *) (h->current),
e1);
if (!strncmp (input->buffer + start,
e1->text, end - start - 1)) {
listbox_select_entry ((WListbox *) (h->current), e1);
end = str_get_prev_char (&(input->buffer[end]))
- input->buffer;
handle_char (input, parm);
end--;
send_message (h->current, WIDGET_DRAW, 0);
break;
}
@ -844,7 +878,8 @@ query_callback (Dlg_head *h, dlg_msg_t msg, int parm)
return MSG_HANDLED;
default:
if (parm > 0xff || !is_printable (parm)) {
if (parm < 32 || parm > 256) {
bl = 0;
if (is_in_input_map (input, parm) == 2) {
if (end == min_end)
return MSG_HANDLED;
@ -860,21 +895,43 @@ query_callback (Dlg_head *h, dlg_msg_t msg, int parm)
int low = 4096;
char *last_text = NULL;
buff[bl] = (char) parm;
bl++;
buff[bl] = '\0';
switch (str_is_valid_char (buff, bl)) {
case -1:
bl = 0;
case -2:
return MSG_HANDLED;
}
e1 = e = ((WListbox *) (h->current))->list;
do {
if (!strncmp
(input->buffer + start, e1->text, end - start)) {
if (e1->text[end - start] == parm) {
if (!strncmp (input->buffer + start,
e1->text, end - start)) {
if (strncmp (&e1->text[end - start], buff, bl) == 0) {
if (need_redraw) {
register int c1, c2, si;
char *si, *sl;
char *ni, *nl;
si = &(e1->text[end - start]);
sl = &(last_text[end - start]);
for (; si[0] != '\0' && sl[0] != '\0';) {
ni = str_get_next_char (si);
nl = str_get_next_char (sl);
if (ni - si != nl - sl) break;
if (strncmp (si, sl, ni - si) != 0) break;
si = ni;
sl = nl;
}
if (low > si - &e1->text[start])
low = si - &e1->text[start];
for (si = end - start + 1;
(c1 = last_text[si])
&& (c2 = e1->text[si]); si++)
if (c1 != c2)
break;
if (low > si)
low = si;
last_text = e1->text;
need_redraw = 2;
} else {
@ -895,6 +952,7 @@ query_callback (Dlg_head *h, dlg_msg_t msg, int parm)
h->ret_value = B_ENTER;
dlg_stop (h);
}
bl = 0;
}
return MSG_HANDLED;
}
@ -911,15 +969,19 @@ query_callback (Dlg_head *h, dlg_msg_t msg, int parm)
static int
complete_engine (WInput *in, int what_to_do)
{
if (in->completions && in->point != end)
int s;
if (in->completions && (str_offset_to_pos (in->buffer, in->point)) != end)
free_completions (in);
if (!in->completions){
end = in->point;
for (start = end ? end - 1 : 0; start > -1; start--)
if (strchr (" \t;|<>", in->buffer [start]))
end = str_offset_to_pos (in->buffer, in->point);
for (s = in->point ? in->point - 1 : 0; s >= 0; s--) {
start = str_offset_to_pos (in->buffer, s);
if (strchr (" \t;|<>", in->buffer [start])) {
if (start < end) start = str_offset_to_pos (in->buffer, s + 1);
break;
if (start < end)
start++;
}
}
in->completions = try_complete (in->buffer, &start, &end, in->completion_flags);
}
if (in->completions){
@ -941,7 +1003,7 @@ complete_engine (WInput *in, int what_to_do)
WListbox *query_list;
for (p=in->completions + 1; *p; count++, p++)
if ((i = strlen (*p)) > maxlen)
if ((i = str_term_width1 (*p)) > maxlen)
maxlen = i;
start_x = in->widget.x;
start_y = in->widget.y;
@ -957,7 +1019,7 @@ complete_engine (WInput *in, int what_to_do)
h = LINES - start_y - 1;
}
}
x = start - in->first_shown - 2 + start_x;
x = start - in->term_first_shown - 2 + start_x;
w = maxlen + 4;
if (x + w > COLS)
x = COLS - w;
@ -999,6 +1061,8 @@ void complete (WInput *in)
{
int engine_flags;
if (!str_is_valid_string (in->buffer)) return;
if (in->completions)
engine_flags = DO_QUERY;
else

Просмотреть файл

@ -789,27 +789,21 @@ gauge_new (int y, int x, int shown, int max, int current)
#endif
#define should_show_history_button(in) \
(in->history && in->field_len > HISTORY_BUTTON_WIDTH * 2 + 1 && in->widget.parent)
(in->history && in->field_width > HISTORY_BUTTON_WIDTH * 2 + 1 && in->widget.parent)
static void draw_history_button (WInput * in)
{
char c;
c = in->history->next ? (in->history->prev ? '|' : 'v') : '^';
widget_move (&in->widget, 0, in->field_len - HISTORY_BUTTON_WIDTH);
widget_move (&in->widget, 0, in->field_width - HISTORY_BUTTON_WIDTH);
#ifdef LARGE_HISTORY_BUTTON
{
Dlg_head *h;
h = in->widget.parent;
#if 0
attrset (NORMALC); /* button has the same color as other buttons */
addstr ("[ ]");
attrset (HOT_NORMALC);
#else
attrset (NORMAL_COLOR);
addstr ("[ ]");
/* Too distracting: attrset (MARKED_COLOR); */
#endif
widget_move (&in->widget, 0, in->field_len - HISTORY_BUTTON_WIDTH + 1);
widget_move (&in->widget, 0, in->field_width - HISTORY_BUTTON_WIDTH + 1);
addch (c);
}
#else
@ -829,9 +823,10 @@ void
update_input (WInput *in, int clear_first)
{
int has_history = 0;
int i, j;
unsigned char c;
int buf_len = strlen (in->buffer);
int i;
int buf_len = str_length (in->buffer);
const char *cp;
int pw;
if (should_show_history_button (in))
has_history = HISTORY_BUTTON_WIDTH;
@ -839,12 +834,15 @@ update_input (WInput *in, int clear_first)
if (in->disable_update)
return;
pw = str_term_width2 (in->buffer, in->point);
/* Make the point visible */
if ((in->point < in->first_shown) ||
(in->point >= in->first_shown+in->field_len - has_history)){
in->first_shown = in->point - (in->field_len / 3);
if (in->first_shown < 0)
in->first_shown = 0;
if ((pw < in->term_first_shown) ||
(pw >= in->term_first_shown + in->field_width - has_history)) {
in->term_first_shown = pw - (in->field_width / 3);
if (in->term_first_shown < 0)
in->term_first_shown = 0;
}
/* Adjust the mark */
@ -857,28 +855,29 @@ update_input (WInput *in, int clear_first)
attrset (in->color);
widget_move (&in->widget, 0, 0);
for (i = 0; i < in->field_len - has_history; i++)
addch (' ');
widget_move (&in->widget, 0, 0);
for (i = 0, j = in->first_shown; i < in->field_len - has_history && in->buffer [j]; i++){
c = in->buffer [j++];
c = is_printable (c) ? c : '.';
if (in->is_password)
c = '*';
addch (c);
if (!in->is_password) {
addstr (str_term_substring (in->buffer, in->term_first_shown,
in->field_width - has_history));
} else {
cp = in->buffer;
for (i = -in->term_first_shown; i < in->field_width - has_history; i++){
if (i >= 0) {
addch ((cp[0] != '\0') ? '*' : ' ');
}
if (cp[0] != '\0') str_cnext_char (&cp);
}
}
widget_move (&in->widget, 0, in->point - in->first_shown);
if (clear_first)
in->first = 0;
}
void
winput_set_origin (WInput *in, int x, int field_len)
winput_set_origin (WInput *in, int x, int field_width)
{
in->widget.x = x;
in->field_len = in->widget.cols = field_len;
in->field_width = in->widget.cols = field_width;
update_input (in, 0);
}
@ -997,11 +996,7 @@ history_put (const char *input_name, GList *h)
static const char *
i18n_htitle (void)
{
static const char *history_title = NULL;
if (history_title == NULL)
history_title = _(" History ");
return history_title;
return _(" History ");
}
static WLEntry *listbox_select_pos (WListbox *l, WLEntry *base, int
@ -1021,7 +1016,7 @@ char *
show_hist (GList *history, int widget_x, int widget_y)
{
GList *hi, *z;
size_t maxlen = strlen (i18n_htitle ()), i, count = 0;
size_t maxlen = str_term_width1 (i18n_htitle ()), i, count = 0;
int x, y, w, h;
char *q, *r = 0;
Dlg_head *query_dlg;
@ -1034,7 +1029,7 @@ show_hist (GList *history, int widget_x, int widget_y)
z = g_list_first (history);
hi = z;
while (hi) {
if ((i = strlen ((char *) hi->data)) > maxlen)
if ((i = str_term_width1 ((char *) hi->data)) > maxlen)
maxlen = i;
count++;
hi = g_list_next (hi);
@ -1202,37 +1197,75 @@ new_input (WInput *in)
if (in->buffer)
push_history (in, in->buffer);
in->need_push = 1;
in->buffer [0] = 0;
in->buffer[0] = '\0';
in->point = 0;
in->charpoint = 0;
in->mark = 0;
free_completions (in);
update_input (in, 0);
}
static void
move_buffer_backward (WInput *in, int start, int end)
{
int i, pos, len;
int str_len = str_length (in->buffer);
if (start >= str_len || end > str_len + 1) return;
pos = str_offset_to_pos (in->buffer, start);
len = str_offset_to_pos (in->buffer, end) - pos;
for (i = pos; in->buffer[i + len - 1]; i++)
in->buffer[i] = in->buffer[i + len];
}
static cb_ret_t
insert_char (WInput *in, int c_code)
{
size_t i;
int res;
if (c_code == -1)
return MSG_NOT_HANDLED;
if (in->charpoint >= MB_LEN_MAX) return 1;
in->charbuf[in->charpoint] = c_code;
in->charpoint++;
res = str_is_valid_char (in->charbuf, in->charpoint);
if (res < 0) {
if (res != -2) in->charpoint = 0; /* broken multibyte char, skip */
return 1;
}
in->need_push = 1;
if (strlen (in->buffer)+1 == (size_t) in->current_max_len){
if (strlen (in->buffer) + 1 + in->charpoint >= in->current_max_size){
/* Expand the buffer */
char *narea = g_realloc (in->buffer, in->current_max_len + in->field_len);
size_t new_length = in->current_max_size +
in->field_width + in->charpoint;
char *narea = g_try_renew (char, in->buffer, new_length);
if (narea){
in->buffer = narea;
in->current_max_len += in->field_len;
in->current_max_size = new_length;
}
}
if (strlen (in->buffer)+1 < (size_t) in->current_max_len){
size_t l = strlen (&in->buffer [in->point]);
for (i = l+1; i > 0; i--)
in->buffer [in->point+i] = in->buffer [in->point+i-1];
in->buffer [in->point] = c_code;
if (strlen (in->buffer) + in->charpoint < in->current_max_size) {
/* bytes from begin */
size_t ins_point = str_offset_to_pos (in->buffer, in->point);
/* move chars */
size_t rest_bytes = strlen (in->buffer + ins_point);
for (i = rest_bytes + 1; i > 0; i--)
in->buffer[ins_point + i + in->charpoint - 1] =
in->buffer[ins_point + i - 1];
memcpy(in->buffer + ins_point, in->charbuf, in->charpoint);
in->point++;
}
in->charpoint = 0;
return MSG_HANDLED;
}
@ -1240,54 +1273,70 @@ static void
beginning_of_line (WInput *in)
{
in->point = 0;
in->charpoint = 0;
}
static void
end_of_line (WInput *in)
{
in->point = strlen (in->buffer);
in->point = str_length (in->buffer);
in->charpoint = 0;
}
static void
backward_char (WInput *in)
{
if (in->point)
in->point--;
const char *act = in->buffer + str_offset_to_pos (in->buffer, in->point);
if (in->point > 0) {
in->point-= str_cprev_noncomb_char (&act, in->buffer);
}
in->charpoint = 0;
}
static void
forward_char (WInput *in)
{
if (in->buffer [in->point])
in->point++;
const char *act = in->buffer + str_offset_to_pos (in->buffer, in->point);
if (act[0] != '\0') {
in->point+= str_cnext_noncomb_char (&act);
}
in->charpoint = 0;
}
static void
forward_word (WInput * in)
{
char *p = in->buffer + in->point;
const char *p = in->buffer + str_offset_to_pos (in->buffer, in->point);
while (*p
&& (isspace ((unsigned char) *p)
|| ispunct ((unsigned char) *p)))
p++;
while (*p && isalnum ((unsigned char) *p))
p++;
in->point = p - in->buffer;
while (p[0] != '\0' && (str_isspace (p) || str_ispunct (p))) {
str_cnext_char (&p);
in->point++;
}
while (p[0] != '\0' && !str_isspace (p) && !str_ispunct (p)) {
str_cnext_char (&p);
in->point++;
}
}
static void
backward_word (WInput *in)
{
char *p = in->buffer + in->point;
const char *p = in->buffer + str_offset_to_pos (in->buffer, in->point);
while (p - 1 > in->buffer - 1 && (isspace ((unsigned char) *(p - 1))
|| ispunct ((unsigned char)
*(p - 1))))
while ((p != in->buffer) && (p[0] == '\0')) {
p--;
while (p - 1 > in->buffer - 1 && isalnum ((unsigned char) *(p - 1)))
p--;
in->point = p - in->buffer;
in->point--;
}
while ((p != in->buffer) && (str_isspace (p) || str_ispunct (p))) {
str_cprev_char (&p);
in->point--;
}
while ((p != in->buffer) && !str_isspace (p) && !str_ispunct (p)) {
str_cprev_char (&p);
in->point--;
}
}
static void
@ -1316,23 +1365,29 @@ key_ctrl_right (WInput *in)
static void
backward_delete (WInput *in)
{
int i;
const char *act = in->buffer + str_offset_to_pos (in->buffer, in->point);
int start;
if (!in->point)
if (in->point == 0)
return;
for (i = in->point; in->buffer [i-1]; i++)
in->buffer [i-1] = in->buffer [i];
start = in->point - str_cprev_noncomb_char (&act, in->buffer);
move_buffer_backward(in, start, in->point);
in->charpoint = 0;
in->need_push = 1;
in->point--;
in->point = start;
}
static void
delete_char (WInput *in)
{
int i;
const char *act = in->buffer + str_offset_to_pos (in->buffer, in->point);
int end = in->point;
end+= str_cnext_noncomb_char (&act);
for (i = in->point; in->buffer [i]; i++)
in->buffer [i] = in->buffer [i+1];
move_buffer_backward(in, in->point, end);
in->charpoint = 0;
in->need_push = 1;
}
@ -1347,7 +1402,10 @@ copy_region (WInput *in, int x_first, int x_last)
g_free (kill_buffer);
kill_buffer = g_strndup(in->buffer+first,last-first);
first = str_offset_to_pos (in->buffer, first);
last = str_offset_to_pos (in->buffer, last);
kill_buffer = g_strndup(in->buffer + first, last - first);
}
static void
@ -1355,11 +1413,15 @@ delete_region (WInput *in, int x_first, int x_last)
{
int first = min (x_first, x_last);
int last = max (x_first, x_last);
size_t len = strlen (&in->buffer [last]) + 1;
size_t len;
in->point = first;
in->mark = first;
memmove (&in->buffer [first], &in->buffer [last], len);
last = str_offset_to_pos (in->buffer, last);
first = str_offset_to_pos (in->buffer, first);
len = strlen (&in->buffer[last]) + 1;
memmove (&in->buffer[first], &in->buffer[last], len);
in->charpoint = 0;
in->need_push = 1;
}
@ -1376,6 +1438,8 @@ kill_word (WInput *in)
copy_region (in, old_point, new_point);
delete_region (in, old_point, new_point);
in->need_push = 1;
in->charpoint = 0;
in->charpoint = 0;
}
static void
@ -1419,16 +1483,20 @@ yank (WInput *in)
if (!kill_buffer)
return;
in->charpoint = 0;
for (p = kill_buffer; *p; p++)
insert_char (in, *p);
in->charpoint = 0;
}
static void
kill_line (WInput *in)
{
int chp = str_offset_to_pos (in->buffer, in->point);
g_free (kill_buffer);
kill_buffer = g_strdup (&in->buffer [in->point]);
in->buffer [in->point] = 0;
kill_buffer = g_strdup (&in->buffer[chp]);
in->buffer[chp] = '\0';
in->charpoint = 0;
}
void
@ -1437,10 +1505,11 @@ assign_text (WInput *in, const char *text)
free_completions (in);
g_free (in->buffer);
in->buffer = g_strdup (text); /* was in->buffer->text */
in->current_max_len = strlen (in->buffer) + 1;
in->point = strlen (in->buffer);
in->current_max_size = strlen (in->buffer) + 1;
in->point = str_length (in->buffer);
in->mark = 0;
in->need_push = 1;
in->charpoint = 0;
}
static void
@ -1564,9 +1633,10 @@ is_in_input_map (WInput *in, int c_code)
static void
port_region_marked_for_delete (WInput *in)
{
*in->buffer = 0;
in->buffer[0] = '\0';
in->point = 0;
in->first = 0;
in->charpoint = 0;
}
cb_ret_t
@ -1595,7 +1665,7 @@ handle_char (WInput *in, int c_code)
}
}
if (!input_map [i].fn){
if (c_code > 255 || !is_printable (c_code))
if (c_code > 255)
return MSG_NOT_HANDLED;
if (in->first){
port_region_marked_for_delete (in);
@ -1623,11 +1693,14 @@ stuff (WInput *in, const char *text, int insert_extra_space)
void
input_set_point (WInput *in, int pos)
{
if (pos > in->current_max_len)
pos = in->current_max_len;
int max_pos = str_length (in->buffer);
if (pos > max_pos)
pos = max_pos;
if (pos != in->point)
free_completions (in);
in->point = pos;
in->charpoint = 0;
update_input (in, 1);
}
@ -1668,7 +1741,8 @@ input_callback (Widget *w, widget_msg_t msg, int parm)
return MSG_HANDLED;
case WIDGET_CURSOR:
widget_move (&in->widget, 0, in->point - in->first_shown);
widget_move (&in->widget, 0, str_term_width2 (in->buffer, in->point)
- in->term_first_shown);
return MSG_HANDLED;
case WIDGET_DESTROY:
@ -1688,15 +1762,17 @@ input_event (Gpm_Event * event, void *data)
if (event->type & (GPM_DOWN | GPM_DRAG)) {
dlg_select_widget (in);
if (event->x >= in->field_len - HISTORY_BUTTON_WIDTH + 1
if (event->x >= in->field_width - HISTORY_BUTTON_WIDTH + 1
&& should_show_history_button (in)) {
do_show_hist (in);
} else {
in->point = strlen (in->buffer);
if (event->x - in->first_shown - 1 < in->point)
in->point = event->x - in->first_shown - 1;
if (in->point < 0)
in->point = 0;
in->point = str_length (in->buffer);
if (event->x + in->term_first_shown - 1 <
str_term_width1 (in->buffer))
in->point = str_column_to_pos (in->buffer, event->x
+ in->term_first_shown - 1);
}
update_input (in, 1);
}
@ -1704,13 +1780,13 @@ input_event (Gpm_Event * event, void *data)
}
WInput *
input_new (int y, int x, int color, int len, const char *def_text,
input_new (int y, int x, int color, int width, const char *def_text,
const char *histname)
{
WInput *in = g_new (WInput, 1);
int initial_buffer_len;
init_widget (&in->widget, y, x, 1, len, input_callback, input_event);
init_widget (&in->widget, y, x, 1, width, input_callback, input_event);
/* history setup */
in->history = NULL;
@ -1722,7 +1798,7 @@ input_new (int y, int x, int color, int len, const char *def_text,
}
}
if (!def_text)
if (def_text == NULL)
def_text = "";
if (def_text == INPUT_LAST_TEXT) {
@ -1731,29 +1807,29 @@ input_new (int y, int x, int color, int len, const char *def_text,
if (in->history->data)
def_text = (char *) in->history->data;
}
initial_buffer_len = 1 + max ((size_t) len, strlen (def_text));
initial_buffer_len = 1 + max ((size_t) width, strlen (def_text));
in->widget.options |= W_IS_INPUT;
in->completions = NULL;
in->completion_flags =
INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_HOSTNAMES |
INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES;
in->current_max_len = initial_buffer_len;
in->buffer = g_malloc (initial_buffer_len);
in->current_max_size = initial_buffer_len;
in->buffer = g_new (char, initial_buffer_len);
in->color = color;
in->field_len = len;
in->field_width = width;
in->first = 1;
in->first_shown = 0;
in->term_first_shown = 0;
in->disable_update = 0;
in->mark = 0;
in->need_push = 1;
in->is_password = 0;
strcpy (in->buffer, def_text);
in->point = strlen (in->buffer);
in->point = str_length (in->buffer);
in->charpoint = 0;
return in;
}
/* Listbox widget */
/* Should draw the scrollbar, but currently draws only

Просмотреть файл

@ -74,11 +74,11 @@ char *show_hist (GList *history, int widget_y, int widget_x);
typedef struct {
Widget widget;
int point; /* cursor position in the input line */
int mark; /* The mark position */
int first_shown; /* Index of the first shown character */
int current_max_len; /* Maximum length of input line */
int field_len; /* Length of the editing field */
int point; /* cursor position in the input line in characters */
int mark; /* The mark position in characters */
int term_first_shown; /* column of the first shown character */
size_t current_max_size; /* Maximum length of input line (bytes) */
int field_width; /* width of the editing field */
int color; /* color used */
int first; /* Is first keystroke? */
int disable_update; /* Do we want to skip updates? */
@ -89,6 +89,8 @@ typedef struct {
char **completions; /* Possible completions array */
int completion_flags; /* INPUT_COMPLETE* bitwise flags(complete.h) */
char *history_name; /* name of history for loading and saving */
char charbuf[MB_LEN_MAX]; /* buffer for multibytes characters */
size_t charpoint; /* point to end of mulibyte sequence in charbuf */
} WInput;
/* For history load-save functions */
@ -144,14 +146,14 @@ WButton *button_new (int y, int x, int action, int flags, const char *text,
bcback callback);
WRadio *radio_new (int y, int x, int count, const char **text);
WCheck *check_new (int y, int x, int state, const char *text);
WInput *input_new (int y, int x, int color, int len, const char *text, const char *histname);
WInput *input_new (int y, int x, int color, int width, const char *text, const char *histname);
WLabel *label_new (int y, int x, const char *text);
WGauge *gauge_new (int y, int x, int shown, int max, int current);
WListbox *listbox_new (int x, int y, int width, int height, lcback callback);
WGroupbox *groupbox_new (int x, int y, int width, int height, const char *title);
/* Input lines */
void winput_set_origin (WInput *i, int x, int field_len);
void winput_set_origin (WInput *i, int x, int field_width);
cb_ret_t handle_char (WInput *in, int c_code);
int is_in_input_map (WInput *in, int c_code);
void update_input (WInput *in, int clear_first);