--- edit/edit-widget.h +++ edit/edit-widget.h @@ -25,6 +25,11 @@ struct syntax_rule { unsigned char border; }; +struct action { + mc_wchar_t ch; + long flags; +}; + struct WEdit { Widget widget; @@ -38,8 +43,12 @@ struct WEdit { /* dynamic buffers and cursor position for editor: */ long curs1; /* position of the cursor from the beginning of the file. */ long curs2; /* position from the end of the file */ - unsigned char *buffers1[MAXBUFF + 1]; /* all data up to curs1 */ - unsigned char *buffers2[MAXBUFF + 1]; /* all data from end of file down to curs2 */ + mc_wchar_t *buffers1[MAXBUFF + 1]; /* all data up to curs1 */ + mc_wchar_t *buffers2[MAXBUFF + 1]; /* all data from end of file down to curs2 */ + + unsigned char charbuf[MB_LEN_MAX]; + int charpoint; + /* search variables */ long search_start; /* First character to start searching from */ @@ -84,7 +93,7 @@ struct WEdit { /* undo stack and pointers */ unsigned long stack_pointer; - long *undo_stack; + struct action *undo_stack; unsigned long stack_size; unsigned long stack_size_mask; unsigned long stack_bottom; --- edit/edit.c +++ edit/edit.c @@ -97,7 +97,7 @@ static void edit_move_to_prev_col (WEdit #ifndef NO_INLINE_GETBYTE -int edit_get_byte (WEdit * edit, long byte_index) +mc_wchar_t edit_get_byte (WEdit * edit, long byte_index) { unsigned long p; if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0) @@ -129,7 +129,7 @@ edit_init_buffers (WEdit *edit) edit->curs1 = 0; edit->curs2 = 0; - edit->buffers2[0] = g_malloc (EDIT_BUF_SIZE); + edit->buffers2[0] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t)); } /* @@ -156,7 +156,7 @@ edit_load_file_fast (WEdit *edit, const } if (!edit->buffers2[buf2]) - edit->buffers2[buf2] = g_malloc (EDIT_BUF_SIZE); + edit->buffers2[buf2] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t)); mc_read (file, (char *) edit->buffers2[buf2] + EDIT_BUF_SIZE - @@ -166,7 +166,7 @@ edit_load_file_fast (WEdit *edit, const for (buf = buf2 - 1; buf >= 0; buf--) { /* edit->buffers2[0] is already allocated */ if (!edit->buffers2[buf]) - edit->buffers2[buf] = g_malloc (EDIT_BUF_SIZE); + edit->buffers2[buf] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t)); mc_read (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE); } @@ -247,9 +247,45 @@ edit_insert_stream (WEdit * edit, FILE * { int c; long i = 0; - while ((c = fgetc (f)) >= 0) { +#ifndef UTF8 + while ((c = fgetc (f)) != EOF) { edit_insert (edit, c); i++; +#else /* UTF8 */ + unsigned char buf[MB_LEN_MAX]; + int charpos = 0; + mbstate_t mbs; + + + while ((c = fgetc (f)) != EOF) { + mc_wchar_t wc; + int size; + int j; + + buf[charpos++] = c; + + memset (&mbs, 0, sizeof (mbs)); + size = mbrtowc(&wc, buf, charpos, &mbs); + + if (size == -2) + continue; /* incomplete */ + + else if (size >= 0) { + edit_insert (edit, wc); + i++; + charpos = 0; + continue; + } + else { + + /* invalid */ +#ifdef __STDC_ISO_10646__ + for (j=0; jlast_byte; i++) if (fputc (edit_get_byte (edit, i), f) < 0) break; +#else /* UTF8 */ + for (i = 0; i < edit->last_byte; i++) { + mc_wchar_t wc = edit_get_byte (edit, i); + int res; + char tmpbuf[MB_LEN_MAX]; + mbstate_t mbs; + + memset (&mbs, 0, sizeof (mbs)); + +#ifdef __STDC_ISO_10646__ + if (wc >= BINARY_CHAR_OFFSET && wc < (BINARY_CHAR_OFFSET + 256)) { + res = 1; + tmpbuf[0] = (char) (wc - BINARY_CHAR_OFFSET); + } else +#endif + res = wcrtomb(tmpbuf, wc, &mbs); + if (res > 0) { + if (fwrite(tmpbuf, res, 1, f) != 1) + break; + } + } +#endif /* UTF8 */ return i; } @@ -299,12 +358,46 @@ edit_insert_file (WEdit *edit, const cha int i, file, blocklen; long current = edit->curs1; unsigned char *buf; +#ifdef UTF8 + mbstate_t mbs; + int bufstart = 0; + + memset (&mbs, 0, sizeof (mbs)); +#endif /* UTF8 */ if ((file = mc_open (filename, O_RDONLY | O_BINARY)) == -1) return 0; buf = g_malloc (TEMP_BUF_LEN); +#ifndef UTF8 while ((blocklen = mc_read (file, (char *) buf, TEMP_BUF_LEN)) > 0) { for (i = 0; i < blocklen; i++) edit_insert (edit, buf[i]); +#else /* UTF8 */ + while ((blocklen = mc_read (file, (char *) buf + bufstart, TEMP_BUF_LEN - bufstart)) > 0) { + blocklen += bufstart; + bufstart = 0; + for (i = 0; i < blocklen; ) { + mc_wchar_t wc; + int j; + int size = mbrtowc(&wc, buf + i, blocklen - i, &mbs); + if (size == -2) { /*incomplete char*/ + bufstart = blocklen - i; + memcpy(buf, buf+i, bufstart); + i = blocklen; + memset (&mbs, 0, sizeof (mbs)); + } + else if (size <= 0) { +#ifdef __STDC_ISO_10646__ + edit_insert (edit, BINARY_CHAR_OFFSET + (mc_wchar_t)buf[i]); +#endif + memset (&mbs, 0, sizeof (mbs)); + i++; /* skip broken char */ + } + else { + edit_insert (edit, wc); + i+=size; + } + } +#endif /* UTF8 */ } edit_cursor_move (edit, current - edit->curs1); g_free (buf); @@ -398,7 +491,11 @@ check_file_access (WEdit *edit, const ch static int edit_load_file (WEdit *edit) { +#ifndef UTF8 int fast_load = 1; +#else /* UTF8 */ + int fast_load = 0; /* can't be used with multibyte characters */ +#endif /* UTF8 */ /* Cannot do fast load if a filter is used */ if (edit_find_filter (edit->filename) >= 0) @@ -546,7 +643,7 @@ edit_init (WEdit *edit, int lines, int c edit_set_filename (edit, filename); edit->stack_size = START_STACK_SIZE; edit->stack_size_mask = START_STACK_SIZE - 1; - edit->undo_stack = g_malloc ((edit->stack_size + 10) * sizeof (long)); + edit->undo_stack = g_malloc ((edit->stack_size + 10) * sizeof (struct action)); if (edit_load_file (edit)) { /* edit_load_file already gives an error message */ if (to_free) @@ -569,7 +666,7 @@ edit_init (WEdit *edit, int lines, int c edit_move_display (edit, line - 1); edit_move_to_line (edit, line - 1); } - + edit->charpoint = 0; return edit; } @@ -690,13 +787,24 @@ void edit_push_action (WEdit * edit, lon { unsigned long sp = edit->stack_pointer; unsigned long spm1; - long *t; + + struct action *t; + mc_wchar_t ch = 0; + + if (c == CHAR_INSERT || c == CHAR_INSERT_AHEAD) { + va_list ap; + va_start (ap, c); + ch = va_arg (ap, mc_wint_t); + va_end (ap); + } + + /* first enlarge the stack if necessary */ if (sp > edit->stack_size - 10) { /* say */ if (option_max_undo < 256) option_max_undo = 256; if (edit->stack_size < option_max_undo) { - t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (long)); + t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (struct action)); if (t) { edit->undo_stack = t; edit->stack_size <<= 1; @@ -711,7 +819,7 @@ void edit_push_action (WEdit * edit, lon #ifdef FAST_MOVE_CURSOR if (c == CURS_LEFT_LOTS || c == CURS_RIGHT_LOTS) { va_list ap; - edit->undo_stack[sp] = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT; + edit->undo_stack[sp].flags = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT; edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask; va_start (ap, c); c = -(va_arg (ap, int)); @@ -722,12 +830,14 @@ void edit_push_action (WEdit * edit, lon && spm1 != edit->stack_bottom && ((sp - 2) & edit->stack_size_mask) != edit->stack_bottom) { int d; - if (edit->undo_stack[spm1] < 0) { - d = edit->undo_stack[(sp - 2) & edit->stack_size_mask]; - if (d == c) { - if (edit->undo_stack[spm1] > -1000000000) { + mc_wchar_t d_ch; + if (edit->undo_stack[spm1].flags < 0) { + d = edit->undo_stack[(sp - 2) & edit->stack_size_mask].flags; + d_ch = edit->undo_stack[(sp - 2) & edit->stack_size_mask].ch; + if (d == c && d_ch == ch) { + if (edit->undo_stack[spm1].flags > -1000000000) { if (c < KEY_PRESS) /* --> no need to push multiple do-nothings */ - edit->undo_stack[spm1]--; + edit->undo_stack[spm1].flags--; return; } } @@ -735,19 +845,20 @@ void edit_push_action (WEdit * edit, lon #ifndef NO_STACK_CURSMOVE_ANIHILATION else if ((c == CURS_LEFT && d == CURS_RIGHT) || (c == CURS_RIGHT && d == CURS_LEFT)) { /* a left then a right anihilate each other */ - if (edit->undo_stack[spm1] == -2) + if (edit->undo_stack[spm1].flags == -2) edit->stack_pointer = spm1; else - edit->undo_stack[spm1]++; + edit->undo_stack[spm1].flags++; return; } #endif } else { - d = edit->undo_stack[spm1]; - if (d == c) { + d = edit->undo_stack[spm1].flags; + d_ch = edit->undo_stack[spm1].ch; + if (d == c && d_ch == ch) { if (c >= KEY_PRESS) return; /* --> no need to push multiple do-nothings */ - edit->undo_stack[sp] = -2; + edit->undo_stack[sp].flags = -2; goto check_bottom; } #ifndef NO_STACK_CURSMOVE_ANIHILATION @@ -759,7 +870,9 @@ void edit_push_action (WEdit * edit, lon #endif } } - edit->undo_stack[sp] = c; + edit->undo_stack[sp].flags = c; + edit->undo_stack[sp].ch = ch; + check_bottom: edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask; @@ -769,10 +882,10 @@ void edit_push_action (WEdit * edit, lon if (c == edit->stack_bottom || ((c + 1) & edit->stack_size_mask) == edit->stack_bottom) do { edit->stack_bottom = (edit->stack_bottom + 1) & edit->stack_size_mask; - } while (edit->undo_stack[edit->stack_bottom] < KEY_PRESS && edit->stack_bottom != edit->stack_pointer); + } while (edit->undo_stack[edit->stack_bottom].flags < KEY_PRESS && edit->stack_bottom != edit->stack_pointer); /*If a single key produced enough pushes to wrap all the way round then we would notice that the [stack_bottom] does not contain KEY_PRESS. The stack is then initialised: */ - if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom] < KEY_PRESS) + if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom].flags < KEY_PRESS) edit->stack_bottom = edit->stack_pointer = 0; } @@ -781,30 +894,30 @@ void edit_push_action (WEdit * edit, lon then the file should be as it was when he loaded up. Then set edit->modified to 0. */ static long -pop_action (WEdit * edit) +pop_action (WEdit * edit, struct action *c) { - long c; unsigned long sp = edit->stack_pointer; if (sp == edit->stack_bottom) { - return STACK_BOTTOM; + c->flags = STACK_BOTTOM; + return c->flags; } sp = (sp - 1) & edit->stack_size_mask; - if ((c = edit->undo_stack[sp]) >= 0) { -/* edit->undo_stack[sp] = '@'; */ + *c = edit->undo_stack[sp]; + if (edit->undo_stack[sp].flags >= 0) { edit->stack_pointer = (edit->stack_pointer - 1) & edit->stack_size_mask; - return c; + return c->flags; } if (sp == edit->stack_bottom) { return STACK_BOTTOM; } - c = edit->undo_stack[(sp - 1) & edit->stack_size_mask]; - if (edit->undo_stack[sp] == -2) { -/* edit->undo_stack[sp] = '@'; */ + *c = edit->undo_stack[(sp - 1) & edit->stack_size_mask]; + + if (edit->undo_stack[sp].flags == -2) { edit->stack_pointer = sp; } else - edit->undo_stack[sp]++; + edit->undo_stack[sp].flags++; - return c; + return c->flags; } /* is called whenever a modification is made by one of the four routines below */ @@ -821,7 +934,7 @@ static inline void edit_modification (WE */ void -edit_insert (WEdit *edit, int c) +edit_insert (WEdit *edit, mc_wchar_t c) { /* check if file has grown to large */ if (edit->last_byte >= SIZE_LIMIT) @@ -855,12 +968,11 @@ edit_insert (WEdit *edit, int c) /* add a new buffer if we've reached the end of the last one */ if (!(edit->curs1 & M_EDIT_BUF_SIZE)) edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = - g_malloc (EDIT_BUF_SIZE); + g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t)); /* perform the insertion */ - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit-> - curs1 & M_EDIT_BUF_SIZE] - = (unsigned char) c; + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] + [edit->curs1 & M_EDIT_BUF_SIZE] = c; /* update file length */ edit->last_byte++; @@ -871,7 +983,7 @@ edit_insert (WEdit *edit, int c) /* same as edit_insert and move left */ -void edit_insert_ahead (WEdit * edit, int c) +void edit_insert_ahead (WEdit * edit, mc_wchar_t c) { if (edit->last_byte >= SIZE_LIMIT) return; @@ -894,7 +1006,7 @@ void edit_insert_ahead (WEdit * edit, in edit->last_get_rule += (edit->last_get_rule >= edit->curs1); if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE)) - edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE); + edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t)); edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c; edit->last_byte++; @@ -904,7 +1016,7 @@ void edit_insert_ahead (WEdit * edit, in int edit_delete (WEdit * edit) { - int p; + mc_wint_t p; if (!edit->curs2) return 0; @@ -927,7 +1039,7 @@ int edit_delete (WEdit * edit) edit->total_lines--; edit->force |= REDRAW_AFTER_CURSOR; } - edit_push_action (edit, p + 256); + edit_push_action (edit, CHAR_INSERT_AHEAD, p); if (edit->curs1 < edit->start_display) { edit->start_display--; if (p == '\n') @@ -942,7 +1054,7 @@ int edit_delete (WEdit * edit) static int edit_backspace (WEdit * edit) { - int p; + mc_wint_t p; if (!edit->curs1) return 0; @@ -965,7 +1077,7 @@ edit_backspace (WEdit * edit) edit->total_lines--; edit->force |= REDRAW_AFTER_CURSOR; } - edit_push_action (edit, p); + edit_push_action (edit, CHAR_INSERT, p); if (edit->curs1 < edit->start_display) { edit->start_display--; @@ -979,10 +1091,18 @@ edit_backspace (WEdit * edit) #ifdef FAST_MOVE_CURSOR -static void memqcpy (WEdit * edit, unsigned char *dest, unsigned char *src, int n) +static void memqcpy (WEdit * edit, mc_wchar_t *dest, mc_wchar_t *src, int n) { unsigned long next; +#ifndef UTF8 while ((next = (unsigned long) memccpy (dest, src, '\n', n))) { +#else /* UTF8 */ + while (n) { + next = 0; + while (next < n && src[next]!='\n') next++; + if (next < n) next++; + wmemcpy (dest, src, next) +#endif /* UTF8 */ edit->curs_line--; next -= (unsigned long) dest; n -= next; @@ -995,7 +1115,7 @@ int edit_move_backward_lots (WEdit *edit, long increment) { int r, s, t; - unsigned char *p; + mc_wchar_t *p; if (increment > edit->curs1) increment = edit->curs1; @@ -1035,7 +1155,7 @@ edit_move_backward_lots (WEdit *edit, lo edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p; else edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = - g_malloc (EDIT_BUF_SIZE); + g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t)); } else { if (p) g_free (p); @@ -1074,7 +1194,7 @@ edit_move_backward_lots (WEdit *edit, lo edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p; else edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = - g_malloc (EDIT_BUF_SIZE); + g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t)); } else { g_free (p); } @@ -1106,7 +1226,7 @@ int edit_cursor_move (WEdit * edit, long c = edit_get_byte (edit, edit->curs1 - 1); if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE)) - edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE); + edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t)); edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c; edit->curs2++; c = edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE][(edit->curs1 - 1) & M_EDIT_BUF_SIZE]; @@ -1131,7 +1251,7 @@ int edit_cursor_move (WEdit * edit, long c = edit_get_byte (edit, edit->curs1); if (!(edit->curs1 & M_EDIT_BUF_SIZE)) - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE); + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t)); edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = c; edit->curs1++; c = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1]; @@ -1238,7 +1358,7 @@ long edit_move_forward3 (WEdit * edit, l q = edit->last_byte + 2; for (col = 0, p = current; p < q; p++) { - int c; + mc_wchar_t c; if (cols != -10) { if (col == cols) return p; @@ -1256,7 +1376,7 @@ long edit_move_forward3 (WEdit * edit, l } else if (c < 32 || c == 127) col += 2; /* Caret notation for control characters */ else - col++; + col+=wcwidth(c); } return col; } @@ -1389,7 +1509,7 @@ static int is_blank (WEdit *edit, long offset) { long s, f; - int c; + mc_wchar_t c; s = edit_bol (edit, offset); f = edit_eol (edit, offset) - 1; while (s <= f) { @@ -1624,11 +1744,11 @@ edit_get_selection (WEdit *edit) selection_history[current_selection].text = g_malloc (selection_history[current_selection].len + 1); if (!selection_history[current_selection].text) { - selection_history[current_selection].text = g_malloc (1); + selection_history[current_selection].text = g_malloc (sizeof(mc_wchar_t)); *selection_history[current_selection].text = 0; selection_history[current_selection].len = 0; } else { - unsigned char *p = selection_history[current_selection].text; + mc_wchar_t *p = selection_history[current_selection].text; for (; start_mark < end_mark; start_mark++) *p++ = edit_get_byte (edit, start_mark); *p = 0; @@ -1787,13 +1907,13 @@ static void edit_left_delete_word (WEdit static void edit_do_undo (WEdit * edit) { - long ac; + struct action ac; long count = 0; edit->stack_disable = 1; /* don't record undo's onto undo stack! */ - while ((ac = pop_action (edit)) < KEY_PRESS) { - switch ((int) ac) { + while (pop_action (edit, &ac) < KEY_PRESS) { + switch ((int) ac.flags) { case STACK_BOTTOM: goto done_undo; case CURS_RIGHT: @@ -1814,31 +1934,33 @@ edit_do_undo (WEdit * edit) case COLUMN_OFF: column_highlighting = 0; break; + case CHAR_INSERT: + edit_insert (edit, ac.ch); + break; + case CHAR_INSERT_AHEAD: + edit_insert_ahead (edit, ac.ch); + break; } - if (ac >= 256 && ac < 512) - edit_insert_ahead (edit, ac - 256); - if (ac >= 0 && ac < 256) - edit_insert (edit, ac); - if (ac >= MARK_1 - 2 && ac < MARK_2 - 2) { - edit->mark1 = ac - MARK_1; + if (ac.flags >= MARK_1 - 2 && ac.flags < MARK_2 - 2) { + edit->mark1 = ac.flags - MARK_1; edit->column1 = edit_move_forward3 (edit, edit_bol (edit, edit->mark1), 0, edit->mark1); - } else if (ac >= MARK_2 - 2 && ac < KEY_PRESS) { - edit->mark2 = ac - MARK_2; + } else if (ac.flags >= MARK_2 - 2 && ac.flags < KEY_PRESS) { + edit->mark2 = ac.flags - MARK_2; edit->column2 = edit_move_forward3 (edit, edit_bol (edit, edit->mark2), 0, edit->mark2); } if (count++) edit->force |= REDRAW_PAGE; /* more than one pop usually means something big */ } - if (edit->start_display > ac - KEY_PRESS) { - edit->start_line -= edit_count_lines (edit, ac - KEY_PRESS, edit->start_display); + if (edit->start_display > ac.flags - KEY_PRESS) { + edit->start_line -= edit_count_lines (edit, ac.flags - KEY_PRESS, edit->start_display); edit->force |= REDRAW_PAGE; - } else if (edit->start_display < ac - KEY_PRESS) { - edit->start_line += edit_count_lines (edit, edit->start_display, ac - KEY_PRESS); + } else if (edit->start_display < ac.flags - KEY_PRESS) { + edit->start_line += edit_count_lines (edit, edit->start_display, ac.flags - KEY_PRESS); edit->force |= REDRAW_PAGE; } - edit->start_display = ac - KEY_PRESS; /* see push and pop above */ + edit->start_display = ac.flags - KEY_PRESS; /* see push and pop above */ edit_update_curs_row (edit); done_undo:; @@ -2114,7 +2236,7 @@ static void edit_goto_matching_bracket ( /* one of command or char_for_insertion must be passed as -1 */ /* commands are executed, and char_for_insertion is inserted at the cursor */ /* returns 0 if the command is a macro that was not found, 1 otherwise */ -int edit_execute_key_command (WEdit * edit, int command, int char_for_insertion) +int edit_execute_key_command (WEdit * edit, int command, mc_wint_t char_for_insertion) { int r; if (command == CK_Begin_Record_Macro) { @@ -2153,7 +2275,7 @@ static const char * const shell_cmd[] = Returns 0 if the command is a macro that was not found, 1 otherwise. */ -int edit_execute_cmd (WEdit * edit, int command, int char_for_insertion) +int edit_execute_cmd (WEdit * edit, int command, mc_wint_t char_for_insertion) { int result = 1; edit->force |= REDRAW_LINE; @@ -2183,7 +2305,7 @@ int edit_execute_cmd (WEdit * edit, int return 1; } /* An ordinary key press */ - if (char_for_insertion >= 0) { + if (char_for_insertion != (mc_wint_t) -1) { if (edit->overwrite) { if (edit_get_byte (edit, edit->curs1) != '\n') edit_delete (edit); @@ -2669,7 +2791,7 @@ int edit_execute_cmd (WEdit * edit, int /* either command or char_for_insertion must be passed as -1 */ /* returns 0 if command is a macro that was not found, 1 otherwise */ -int edit_execute_command (WEdit * edit, int command, int char_for_insertion) +int edit_execute_command (WEdit * edit, int command, mc_wint_t char_for_insertion) { int r; r = edit_execute_cmd (edit, command, char_for_insertion); --- edit/edit.h +++ edit/edit.h @@ -22,6 +22,7 @@ #ifndef __EDIT_H #define __EDIT_H +#define _ISOC99_SOURCE #include #include @@ -39,6 +40,26 @@ #include "src/global.h" +#include "src/tty.h" + +#ifdef UTF8 +#include +#include + +#define mc_wchar_t wchar_t +#define mc_wint_t wint_t + +#else + +#define mc_wchar_t unsigned char +#define mc_wint_t int + +#endif + + +/* unicode private use area */ +#define BINARY_CHAR_OFFSET 0xFFE00 + # define WIDGET_COMMAND (WIDGET_USER + 10) # define N_menus 5 @@ -89,6 +110,8 @@ /*some codes that may be pushed onto or returned from the undo stack: */ +#define CHAR_INSERT 65 +#define CHAR_INSERT_AHEAD 66 #define CURS_LEFT 601 #define CURS_RIGHT 602 #define DELCHAR 603 @@ -108,11 +131,11 @@ struct macro { short command; - short ch; + mc_wchar_t ch; }; struct selection { - unsigned char * text; + mc_wchar_t * text; int len; }; @@ -128,12 +151,13 @@ void menu_save_mode_cmd (void); int edit_raw_key_query (char *heading, char *query, int cancel); char *strcasechr (const unsigned char *s, int c); int edit (const char *_file, int line); -int edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch); +int edit_translate_key (WEdit *edit, long x_key, int *cmd, mc_wint_t *ch); -#ifndef NO_INLINE_GETBYTE -int edit_get_byte (WEdit * edit, long byte_index); +//ifndef NO_INLINE_GETBYTE +#if 1 +mc_wchar_t edit_get_byte (WEdit * edit, long byte_index); #else -static inline int edit_get_byte (WEdit * edit, long byte_index) +static inline mc_wchar_t edit_get_byte (WEdit * edit, long byte_index) { unsigned long p; if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0) @@ -173,11 +197,11 @@ int edit_block_delete (WEdit * edit); void edit_delete_line (WEdit * edit); int edit_delete (WEdit * edit); -void edit_insert (WEdit * edit, int c); +void edit_insert (WEdit * edit, mc_wchar_t c); int edit_cursor_move (WEdit * edit, long increment); void edit_push_action (WEdit * edit, long c, ...); void edit_push_key_press (WEdit * edit); -void edit_insert_ahead (WEdit * edit, int c); +void edit_insert_ahead (WEdit * edit, mc_wchar_t c); int edit_save_file (WEdit * edit, const char *filename); long edit_write_stream (WEdit * edit, FILE * f); char *edit_get_write_filter (const char *writename, const char *filename); @@ -210,16 +234,17 @@ void edit_date_cmd (WEdit * edit); void edit_goto_cmd (WEdit * edit); int eval_marks (WEdit * edit, long *start_mark, long *end_mark); void edit_status (WEdit * edit); -int edit_execute_command (WEdit * edit, int command, int char_for_insertion); -int edit_execute_key_command (WEdit * edit, int command, int char_for_insertion); +int edit_execute_command (WEdit * edit, int command, mc_wint_t char_for_insertion); +int edit_execute_key_command (WEdit * edit, int command, mc_wint_t char_for_insertion); void edit_update_screen (WEdit * edit); int edit_printf (WEdit * e, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); int edit_print_string (WEdit * e, const char *s); +int edit_print_wstring (WEdit * e, mc_wchar_t *s); void edit_move_to_line (WEdit * e, long line); void edit_move_display (WEdit * e, long line); void edit_word_wrap (WEdit * edit); -unsigned char *edit_get_block (WEdit * edit, long start, long finish, int *l); +mc_wchar_t *edit_get_block (WEdit * edit, long start, long finish, int *l); int edit_sort_cmd (WEdit * edit); void edit_help_cmd (WEdit * edit); void edit_left_word_move (WEdit * edit, int s); @@ -261,7 +286,7 @@ void edit_mail_dialog (WEdit *edit); void format_paragraph (WEdit *edit, int force); /* either command or char_for_insertion must be passed as -1 */ -int edit_execute_cmd (WEdit * edit, int command, int char_for_insertion); +int edit_execute_cmd (WEdit * edit, int command, mc_wint_t char_for_insertion); #define get_sys_error(s) (s) --- edit/editcmd.c +++ edit/editcmd.c @@ -95,12 +95,13 @@ static void *memmove (void *dest, const } #endif /* !HAVE_MEMMOVE */ -/* #define itoa MY_itoa <---- this line is now in edit.h */ -static char * +/* #define itoa +MY_itoa <---- this line is now in edit.h */ +static mc_wchar_t * MY_itoa (int i) { - static char t[14]; - char *s = t + 13; + static mc_wchar_t t[14]; + mc_wchar_t *s = t + 13; int j = i; *s-- = 0; do { @@ -184,6 +185,48 @@ void edit_refresh_cmd (WEdit * edit) doupdate(); } +#ifdef UTF8 + +static size_t +wchar_write(int fd, mc_wchar_t *buf, size_t len) +{ + char *tmpbuf = g_malloc(len + MB_LEN_MAX); + mbstate_t mbs; + size_t i; + size_t outlen = 0; + size_t res; + + for (i = 0; i < len; i++) { + if (outlen >= len) { + if ((res = mc_write(fd, tmpbuf, outlen)) != outlen) { + g_free(tmpbuf); + return -1; + } + outlen = 0; + } + memset (&mbs, 0, sizeof (mbs)); +#ifdef __STDC_ISO_10646__ + if (buf[i] >= BINARY_CHAR_OFFSET && buf[i] < (BINARY_CHAR_OFFSET + 256)) { + res = 1; + tmpbuf[outlen] = (char) (buf[i] - BINARY_CHAR_OFFSET); + + } else +#endif + res = wcrtomb(tmpbuf + outlen, buf[i], &mbs); + if (res > 0) { + outlen += res; + } + } + if ((res = mc_write(fd, tmpbuf, outlen)) != outlen) { + g_free(tmpbuf); + return -1; + } + g_free(tmpbuf); + return len; +} + +#endif /* UTF8 */ + /* "Oleg Yu. Repin" added backup filenames ...thanks -paul */ @@ -286,32 +329,48 @@ edit_save_file (WEdit *edit, const char buf = 0; filelen = edit->last_byte; while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1) { +#ifndef UTF8 if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE) +#else /* UTF8 */ + if (wchar_write (fd, edit->buffers1[buf], EDIT_BUF_SIZE) +#endif /* UTF8 */ != EDIT_BUF_SIZE) { mc_close (fd); goto error_save; } buf++; } +#ifndef UTF8 if (mc_write (fd, (char *) edit->buffers1[buf], +#else /* UTF8 */ + if (wchar_write + (fd, edit->buffers1[buf], +#endif /* UTF8 */ edit->curs1 & M_EDIT_BUF_SIZE) != (edit->curs1 & M_EDIT_BUF_SIZE)) { filelen = -1; } else if (edit->curs2) { edit->curs2--; buf = (edit->curs2 >> S_EDIT_BUF_SIZE); - if (mc_write - (fd, - (char *) edit->buffers2[buf] + EDIT_BUF_SIZE - +#ifndef UTF8 + if (mc_write(fd, (char *) edit->buffers2[buf] + EDIT_BUF_SIZE - +#else /* UTF8 */ + if (wchar_write(fd, edit->buffers2[buf] + EDIT_BUF_SIZE - +#endif /* UTF8 */ (edit->curs2 & M_EDIT_BUF_SIZE) - 1, 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) != 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) { filelen = -1; } else { while (--buf >= 0) { +#ifndef UTF8 if (mc_write (fd, (char *) edit->buffers2[buf], +#else /* UTF8 */ + if (wchar_write + (fd, edit->buffers2[buf], +#endif /* UTF8 */ EDIT_BUF_SIZE) != EDIT_BUF_SIZE) { filelen = -1; break; @@ -597,13 +656,21 @@ edit_delete_macro (WEdit * edit, int k) if (!n || n == EOF) break; n = 0; +#ifndef UTF8 while (fscanf (f, "%hd %hd, ", ¯o[n].command, ¯o[n].ch)) +#else /* UTF8 */ + while (fscanf (f, "%hd %lu, ", ¯o[n].command, ¯o[n].ch)) +#endif /* UTF8 */ n++; fscanf (f, ";\n"); if (s != k) { fprintf (g, ("key '%d 0': "), s); for (i = 0; i < n; i++) +#ifndef UTF8 fprintf (g, "%hd %hd, ", macro[i].command, macro[i].ch); +#else /* UTF8 */ + fprintf (g, "%hd %lu, ", macro[i].command, macro[i].ch); +#endif /* UTF8 */ fprintf (g, ";\n"); } } @@ -639,7 +706,11 @@ int edit_save_macro_cmd (WEdit * edit, s if (f) { fprintf (f, ("key '%d 0': "), s); for (i = 0; i < n; i++) +#ifndef UTF8 fprintf (f, "%hd %hd, ", macro[i].command, macro[i].ch); +#else /* UTF8 */ + fprintf (f, "%hd %lu, ", macro[i].command, macro[i].ch); +#endif /* UTF8 */ fprintf (f, ";\n"); fclose (f); if (saved_macros_loaded) { @@ -688,10 +759,18 @@ int edit_load_macro_cmd (WEdit * edit, s saved_macro[i++] = s; if (!found) { *n = 0; +#ifndef UTF8 while (*n < MAX_MACRO_LENGTH && 2 == fscanf (f, "%hd %hd, ", ¯o[*n].command, ¯o[*n].ch)) +#else /* UTF8 */ + while (*n < MAX_MACRO_LENGTH && 2 == fscanf (f, "%hd %lu, ", ¯o[*n].command, ¯o[*n].ch)) +#endif /* UTF8 */ (*n)++; } else { +#ifndef UTF8 while (2 == fscanf (f, "%hd %hd, ", &dummy.command, &dummy.ch)); +#else /* UTF8 */ + while (2 == fscanf (f, "%hd %lu, ", &dummy.command, &dummy.ch)); +#endif /* UTF8 */ } fscanf (f, ";\n"); if (s == k) @@ -819,7 +898,7 @@ int eval_marks (WEdit * edit, long *star #define space_width 1 static void -edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width) +edit_insert_column_of_text (WEdit * edit, mc_wchar_t *data, int size, int width) { long cursor; int i, col; @@ -867,7 +946,7 @@ edit_block_copy_cmd (WEdit *edit) { long start_mark, end_mark, current = edit->curs1; int size, x; - unsigned char *copy_buf; + mc_wchar_t *copy_buf; edit_update_curs_col (edit); x = edit->curs_col; @@ -912,7 +991,7 @@ edit_block_move_cmd (WEdit *edit) { long count; long current; - unsigned char *copy_buf; + mc_wchar_t *copy_buf; long start_mark, end_mark; int deleted = 0; int x = 0; @@ -973,7 +1052,7 @@ edit_block_move_cmd (WEdit *edit) edit_push_action (edit, COLUMN_ON); column_highlighting = 0; } else { - copy_buf = g_malloc (end_mark - start_mark); + copy_buf = g_malloc ((end_mark - start_mark) * sizeof(mc_wchar_t)); edit_cursor_move (edit, start_mark - edit->curs1); edit_scroll_screen_over_cursor (edit); count = start_mark; @@ -1303,7 +1382,11 @@ static long sargs[NUM_REPL_ARGS][256 / s /* This function is a modification of mc-3.2.10/src/view.c:regexp_view_search() */ /* returns -3 on error in pattern, -1 on not found, found_len = 0 if either */ static int +#ifndef UTF8 string_regexp_search (char *pattern, char *string, int len, int match_type, +#else /* UTF8 */ +string_regexp_search (char *pattern, mc_wchar_t *wstring, int len, int match_type, +#endif /* UTF8 */ int match_bol, int icase, int *found_len, void *d) { static regex_t r; @@ -1312,6 +1395,12 @@ string_regexp_search (char *pattern, cha regmatch_t *pmatch; static regmatch_t s[1]; +#ifdef UTF8 + char *string; + int i; + +#endif /* UTF8 */ + pmatch = (regmatch_t *) d; if (!pmatch) pmatch = s; @@ -1331,13 +1420,51 @@ string_regexp_search (char *pattern, cha old_type = match_type; old_icase = icase; } + +#ifdef UTF8 + string = wchar_to_mbstr(wstring); + if (string == NULL) + return -1; +#endif /* UTF8 */ + if (regexec (&r, string, d ? NUM_REPL_ARGS : 1, pmatch, ((match_bol || match_type != match_normal) ? 0 : REG_NOTBOL)) != 0) { *found_len = 0; + +#ifdef UTF8 + g_free(string); +#endif /* UTF8 */ + return -1; } + +#ifdef UTF8 + for (i = 0; i < (d ? NUM_REPL_ARGS : 1); i++) { + char tmp; + int new_o; + + if (pmatch[i].rm_so < 0) + continue; + tmp = string[pmatch[i].rm_so]; + string[pmatch[i].rm_so] = 0; + new_o = mbstrlen(string); + string[pmatch[i].rm_so] = tmp; + pmatch[i].rm_so = new_o; + + if (pmatch[i].rm_eo < 0) + continue; + tmp = string[pmatch[i].rm_eo]; + string[pmatch[i].rm_eo] = 0; + new_o = mbstrlen(string); + string[pmatch[i].rm_eo] = tmp; + pmatch[i].rm_eo = new_o; + } + + g_free(string); +#endif /* UTF8 */ + *found_len = pmatch[0].rm_eo - pmatch[0].rm_so; return (pmatch[0].rm_so); } @@ -1346,30 +1473,48 @@ string_regexp_search (char *pattern, cha (and the above) routines to work properly - paul */ static long +#ifndef UTF8 edit_find_string (long start, unsigned char *exp, int *len, long last_byte, int (*get_byte) (void *, long), void *data, int once_only, void *d) +#else /* UTF8 */ +edit_find_string (long start, unsigned char *exp_mb, int *len, long last_byte, int (*get_byte) (void *, long), void *data, int once_only, void *d) +#endif /* UTF8 */ { long p, q = 0; - long l = strlen ((char *) exp), f = 0; + long f = 0; + +#ifndef UTF8 + long l = strlen ((char *) exp); +#else /* UTF8 */ + mc_wchar_t *exp = mbstr_to_wchar(exp_mb); + mc_wchar_t *exp_backup = exp; + long l = wcslen(exp); +#endif /* UTF8 */ int n = 0; + for (p = 0; p < l; p++) /* count conversions... */ if (exp[p] == '%') if (exp[++p] != '%') /* ...except for "%%" */ n++; if (replace_scanf || replace_regexp) { - int c; - unsigned char *buf; - unsigned char mbuf[MAX_REPL_LEN * 2 + 3]; + + mc_wint_t c; + mc_wchar_t *buf; + mc_wchar_t mbuf[MAX_REPL_LEN * 2 + 3]; replace_scanf = (!replace_regexp); /* can't have both */ buf = mbuf; if (replace_scanf) { - unsigned char e[MAX_REPL_LEN]; - if (n >= NUM_REPL_ARGS) + mc_wchar_t e[MAX_REPL_LEN]; + if (n >= NUM_REPL_ARGS) { +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return -3; + } if (replace_case) { for (p = start; p < last_byte && p < start + MAX_REPL_LEN; p++) @@ -1384,20 +1529,36 @@ edit_find_string (long start, unsigned c } buf[(q = p - start)] = 0; +#ifndef UTF8 strcpy ((char *) e, (char *) exp); strcat ((char *) e, "%n"); +#else /* UTF8 */ + wcscpy (e, exp); + wcscat (e, L"%n"); +#endif /* UTF8 */ exp = e; while (q) { *((int *) sargs[n]) = 0; /* --> here was the problem - now fixed: good */ +#ifndef UTF8 if (n == sscanf ((char *) buf, (char *) exp, SCANF_ARGS)) { +#else /* UTF8 */ + if (n == swscanf (buf, exp, SCANF_ARGS)) { +#endif /* UTF8 */ if (*((int *) sargs[n])) { *len = *((int *) sargs[n]); +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return start; } } - if (once_only) + if (once_only) { +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return -2; + } if (q + start < last_byte) { if (replace_case) { buf[q] = (*get_byte) (data, q + start); @@ -1411,7 +1572,11 @@ edit_find_string (long start, unsigned c start++; buf++; /* move the window along */ if (buf == mbuf + MAX_REPL_LEN) { /* the window is about to go past the end of array, so... */ +#ifndef UTF8 memmove (mbuf, buf, strlen ((char *) buf) + 1); /* reset it */ +#else /* UTF8 */ + wmemmove (mbuf, buf, (wcslen (buf) + 1)); /* reset it */ +#endif /* UTF8 */ buf = mbuf; } q--; @@ -1437,10 +1602,17 @@ edit_find_string (long start, unsigned c buf = mbuf; while (q) { +#ifndef UTF8 found_start = string_regexp_search ((char *) exp, (char *) buf, q, match_normal, match_bol, !replace_case, len, d); +#else /* UTF8 */ + found_start = string_regexp_search ((char *) exp_mb, buf, q, match_normal, match_bol, !replace_case, len, d); +#endif /* UTF8 */ if (found_start <= -2) { /* regcomp/regexec error */ *len = 0; +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return -3; } else if (found_start == -1) /* not found: try next line */ @@ -1451,15 +1623,27 @@ edit_find_string (long start, unsigned c match_bol = 0; continue; } - else /* found */ + else { /* found */ +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return (start + offset - q + found_start); + } } - if (once_only) + if (once_only) { +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return -2; + } if (buf[q - 1] != '\n') { /* incomplete line: try to recover */ buf = mbuf + MAX_REPL_LEN / 2; +#ifndef UTF8 q = strlen ((char *) buf); +#else /* UTF8 */ + q = wcslen (buf); +#endif /* UTF8 */ memmove (mbuf, buf, q); p = start + q; move_win = 1; @@ -1469,36 +1653,59 @@ edit_find_string (long start, unsigned c } } } else { +#ifndef UTF8 *len = strlen ((char *) exp); +#else /* UTF8 */ + *len = wcslen (exp); +#endif /* UTF8 */ if (replace_case) { for (p = start; p <= last_byte - l; p++) { - if ((*get_byte) (data, p) == (unsigned char)exp[0]) { /* check if first char matches */ + if ((*get_byte) (data, p) == exp[0]) { /* check if first char matches */ for (f = 0, q = 0; q < l && f < 1; q++) - if ((*get_byte) (data, q + p) != (unsigned char)exp[q]) + if ((*get_byte) (data, q + p) != exp[q]) f = 1; - if (f == 0) + if (f == 0) { +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return p; + } } - if (once_only) + if (once_only) { +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return -2; + } } } else { for (p = 0; exp[p] != 0; p++) exp[p] = my_lower_case (exp[p]); for (p = start; p <= last_byte - l; p++) { - if (my_lower_case ((*get_byte) (data, p)) == (unsigned char)exp[0]) { + if (my_lower_case ((*get_byte) (data, p)) == exp[0]) { for (f = 0, q = 0; q < l && f < 1; q++) - if (my_lower_case ((*get_byte) (data, q + p)) != (unsigned char)exp[q]) + if (my_lower_case ((*get_byte) (data, q + p)) != exp[q]) f = 1; - if (f == 0) + if (f == 0) { +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return p; + } } - if (once_only) + if (once_only) { +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return -2; + } } } } +#ifdef UTF8 + g_free(exp_backup); +#endif /* UTF8 */ return -2; } @@ -1512,9 +1719,14 @@ edit_find_forwards (long search_start, u while ((p = edit_find_string (p, exp, len, last_byte, get_byte, data, once_only, d)) >= 0) { if (replace_whole) { +#ifndef UTF8 /*If the bordering chars are not in option_whole_chars_search then word is whole */ if (!strcasechr (option_whole_chars_search, (*get_byte) (data, p - 1)) && !strcasechr (option_whole_chars_search, (*get_byte) (data, p + *len))) +#else /* UTF8 */ + if (!iswalnum((*get_byte) (data, p - 1)) + && !iswalnum((*get_byte) (data, p + *len))) +#endif /* UTF8 */ return p; if (once_only) return -2; @@ -1546,51 +1758,80 @@ edit_find (long search_start, unsigned c #define is_digit(x) ((x) >= '0' && (x) <= '9') -#define snprintf(v) { \ +#ifndef UTF8 +#define snprint(v) { \ *p1++ = *p++; \ - *p1++ = '%'; \ - *p1++ = 'n'; \ *p1 = '\0'; \ - sprintf(s,q1,v,&n); \ + n = sprintf(s,e-s,q1,v); \ + if (n >= e - s) goto nospc; \ s += n; \ } +#else /* UTF8 */ +#define snprint(v) { \ + *p1++ = *p++; \ + *p1 = '\0'; \ + n = swprintf(s, e-s, q1,v); \ + if (n >= e - s) goto nospc; \ + s += n; \ + } +#endif /* UTF8 */ /* this function uses the sprintf command to do a vprintf */ /* it takes pointers to arguments instead of the arguments themselves */ -static int sprintf_p (char *str, const char *fmt,...) - __attribute__ ((format (printf, 2, 3))); - -static int sprintf_p (char *str, const char *fmt,...) +/* The return value is the number of bytes written excluding '\0' + if successfull, -1 if the resulting string would be too long and + -2 if the format string is errorneous. */ +#ifndef UTF8 +static int snprintf_p (unsigned char *str, size_t size, const char *fmt,...) + __attribute__ ((format (printf, 3, 4))); +static int snprintf_p (unsigned char *str, size_t size, const char *fmt,...) +#else +static int snprintf_p (mc_wchar_t *str, size_t size, const mc_wchar_t *fmt,...) +#endif /* UTF8 */ { va_list ap; - int n; - char *q, *p, *s = str; - char q1[32]; - char *p1; + size_t n; + const mc_wchar_t *q, *p; + mc_wchar_t *s = str; + mc_wchar_t *e = str + size; + mc_wchar_t q1[40]; + + mc_wchar_t *p1; + int nargs = 0; va_start (ap, fmt); - p = q = (char *) fmt; + p = q = fmt; +#ifndef UTF8 while ((p = strchr (p, '%'))) { +#else /* UTF8 */ + while ((p = wcschr (p, L'%'))) { +#endif /* UTF8 */ n = p - q; - strncpy (s, q, n); /* copy stuff between format specifiers */ + if (n >= e - s) + goto nospc; +#ifndef UTF8 + memcpy (s, q, n); /* copy stuff between format specifiers */ +#else /* UTF8 */ + wmemcpy (s, q, n); /* copy stuff between format specifiers */ +#endif /* UTF8 */ s += n; - *s = 0; q = p; p1 = q1; *p1++ = *p++; if (*p == '%') { p++; *s++ = '%'; + if (s == e) + goto nospc; q = p; continue; } - if (*p == 'n') { - p++; -/* do nothing */ - q = p; - continue; - } + if (*p == 'n') + goto err; + /* We were passed only 16 arguments. */ + if (++nargs == 16) + goto err; if (*p == '#') *p1++ = *p++; if (*p == '0') @@ -1601,50 +1842,105 @@ static int sprintf_p (char *str, const c *p1++ = *p++; if (*p == '*') { p++; +#ifndef UTF8 strcpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace field width with a number */ p1 += strlen (p1); +#else /* UTF8 */ + wcscpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace field width with a number */ + p1 += wcslen (p1); +#endif /* UTF8 */ } else { - while (is_digit (*p)) +#ifndef UTF8 + while (is_digit (*p) +#else /* UTF8 */ + while (iswdigit (*p) +#endif /* UTF8 */ + && p1 < q1 + 20) *p1++ = *p++; +#ifndef UTF8 + if (is_digit (*p)) +#else /* UTF8 */ + if (iswdigit (*p)) +#endif /* UTF8 */ + goto err; } if (*p == '.') *p1++ = *p++; if (*p == '*') { p++; +#ifndef UTF8 strcpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace precision with a number */ p1 += strlen (p1); +#else /* UTF8 */ + wcscpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace precision with a number */ + p1 += wcslen (p1); +#endif /* UTF8 */ } else { - while (is_digit (*p)) +#ifndef UTF8 + while (is_digit (*p) +#else /* UTF8 */ + while (iswdigit (*p) +#endif /* UTF8 */ + && p1 < q1 + 32) *p1++ = *p++; +#ifndef UTF8 + if (is_digit (*p)) +#else /* UTF8 */ + if (iswdigit (*p)) +#endif /* UTF8 */ + goto err; } /* flags done, now get argument */ if (*p == 's') { - snprintf (va_arg (ap, char *)); +#ifndef UTF8 + snprint (va_arg (ap, char *)); +#else /* UTF8 */ + *p1++ = 'l'; + snprint (va_arg (ap, mc_wchar_t *)); +#endif /* UTF8 */ } else if (*p == 'h') { - if (strchr ("diouxX", *p)) - snprintf (*va_arg (ap, short *)); + if (*p < 128 && strchr ("diouxX", *p)) + snprint (*va_arg (ap, short *)); } else if (*p == 'l') { *p1++ = *p++; - if (strchr ("diouxX", *p)) - snprintf (*va_arg (ap, long *)); - } else if (strchr ("cdiouxX", *p)) { - snprintf (*va_arg (ap, int *)); + if (*p < 128 && strchr ("diouxX", *p)) + snprint (*va_arg (ap, long *)); + } else if (*p < 128 && strchr ("cdiouxX", *p)) { + snprint (*va_arg (ap, int *)); } else if (*p == 'L') { *p1++ = *p++; - if (strchr ("EefgG", *p)) - snprintf (*va_arg (ap, double *)); /* should be long double */ - } else if (strchr ("EefgG", *p)) { - snprintf (*va_arg (ap, double *)); - } else if (strchr ("DOU", *p)) { - snprintf (*va_arg (ap, long *)); + if (*p < 128 && strchr ("EefgG", *p)) + snprint (*va_arg (ap, double *)); /* should be long double */ + } else if (*p < 128 && strchr ("EefgG", *p)) { + snprint (*va_arg (ap, double *)); + } else if (*p < 128 && strchr ("DOU", *p)) { + snprint (*va_arg (ap, long *)); } else if (*p == 'p') { - snprintf (*va_arg (ap, void **)); - } + snprint (*va_arg (ap, void **)); + } else + goto err; q = p; } va_end (ap); - sprintf (s, q); /* print trailing leftover */ - return s - str + strlen (s); +#ifndef UTF8 + n = strlen (q); + if (n >= e - s) + return -1; + memcpy (s, q, n + 1); + return s + n - str; +#else /* UTF8 */ + n = wcslen (q); + if (n >= e - s) + return -1; + wmemcpy (s, q, n + 1); +#endif /* UTF8 */ + return s + n - str; +nospc: + va_end (ap); + return -1; +err: + va_end (ap); + return -2; } static void regexp_error (WEdit *edit) @@ -1737,7 +2033,7 @@ edit_replace_cmd (WEdit *edit, int again for (i = 0; i < NUM_REPL_ARGS; i++) { if (s != (char *) 1 && *s) { ord = atoi (s); - if ((ord > 0) && (ord < NUM_REPL_ARGS)) + if ((ord > 0) && (ord <= NUM_REPL_ARGS)) argord[i] = ord - 1; else argord[i] = i; @@ -1819,8 +2115,12 @@ edit_replace_cmd (WEdit *edit, int again } } if (replace_yes) { /* delete then insert new */ +#ifdef UTF8 + mc_wchar_t *wexp2 = mbstr_to_wchar(exp2); +#endif /* UTF8 */ if (replace_scanf || replace_regexp) { - char repl_str[MAX_REPL_LEN + 2]; + mc_wchar_t repl_str[MAX_REPL_LEN + 2]; + int ret = 0; /* we need to fill in sargs just like with scanf */ if (replace_regexp) { @@ -1828,12 +2128,17 @@ edit_replace_cmd (WEdit *edit, int again for (k = 1; k < NUM_REPL_ARGS && pmatch[k].rm_eo >= 0; k++) { - unsigned char *t; - t = (unsigned char *) &sargs[k - 1][0]; + mc_wchar_t *t; + + if (pmatch[k].rm_eo - pmatch[k].rm_so > 255) { + ret = -1; + break; + } + t = &sargs[k - 1][0]; for (j = 0; j < pmatch[k].rm_eo - pmatch[k].rm_so && j < 255; j++, t++) - *t = (unsigned char) edit_get_byte (edit, + *t = edit_get_byte (edit, edit-> search_start - @@ -1849,7 +2154,13 @@ edit_replace_cmd (WEdit *edit, int again for (; k <= NUM_REPL_ARGS; k++) sargs[k - 1][0] = 0; } - if (sprintf_p (repl_str, exp2, PRINTF_ARGS) >= 0) { + if (!ret) +#ifndef UTF8 + ret = snprintf_p (repl_str, MAX_REPL_LEN + 2, exp2, PRINTF_ARGS); +#else /* UTF8 */ + ret = snprintf_p (repl_str, MAX_REPL_LEN + 2, wexp2, PRINTF_ARGS); +#endif /* UTF8 */ + if (ret >= 0) { times_replaced++; while (i--) edit_delete (edit); @@ -1857,18 +2168,27 @@ edit_replace_cmd (WEdit *edit, int again edit_insert (edit, repl_str[i]); } else { edit_error_dialog (_(" Replace "), - _ - (" Error in replacement format string. ")); + ret == -2 + ? _(" Error in replacement format string. ") + : _(" Replacement too long. ")); replace_continue = 0; } } else { times_replaced++; while (i--) edit_delete (edit); +#ifndef UTF8 while (exp2[++i]) edit_insert (edit, exp2[i]); +#else /* UTF8 */ + while (wexp2[++i]) + edit_insert (edit, wexp2[i]); +#endif /* UTF8 */ } edit->found_len = i; +#ifdef UTF8 + g_free(wexp2); +#endif /* UTF8 */ } /* so that we don't find the same string again */ if (replace_backwards) { @@ -2039,16 +2359,17 @@ void edit_quit_cmd (WEdit * edit) #define TEMP_BUF_LEN 1024 /* Return a null terminated length of text. Result must be g_free'd */ -unsigned char * +mc_wchar_t * edit_get_block (WEdit *edit, long start, long finish, int *l) { - unsigned char *s, *r; - r = s = g_malloc (finish - start + 1); + mc_wchar_t *s, *r; + r = s = g_malloc ((finish - start + 1) * sizeof(mc_wchar_t)); if (column_highlighting) { *l = 0; /* copy from buffer, excluding chars that are out of the column 'margins' */ while (start < finish) { - int c, x; + mc_wchar_t c; + int x; x = edit_move_forward3 (edit, edit_bol (edit, start), 0, start); c = edit_get_byte (edit, start); @@ -2081,11 +2402,15 @@ edit_save_block (WEdit * edit, const cha return 0; if (column_highlighting) { - unsigned char *block, *p; + mc_wchar_t *block, *p; int r; p = block = edit_get_block (edit, start, finish, &len); while (len) { +#ifndef UTF8 r = mc_write (file, p, len); +#else /* UTF8 */ + r = wchar_write (file, p, len); +#endif /* UTF8 */ if (r < 0) break; p += r; @@ -2093,15 +2418,19 @@ edit_save_block (WEdit * edit, const cha } g_free (block); } else { - unsigned char *buf; + mc_wchar_t *buf; int i = start, end; len = finish - start; - buf = g_malloc (TEMP_BUF_LEN); + buf = g_malloc (TEMP_BUF_LEN * sizeof(mc_wchar_t)); while (start != finish) { end = min (finish, start + TEMP_BUF_LEN); for (; i < end; i++) buf[i - start] = edit_get_byte (edit, i); +#ifndef UTF8 len -= mc_write (file, (char *) buf, end - start); +#else /* UTF8 */ + len -= wchar_write (file, buf, end - start); +#endif /* UTF8 */ start = end; } g_free (buf); @@ -2407,16 +2736,31 @@ edit_block_process_cmd (WEdit *edit, con /* prints at the cursor */ /* returns the number of chars printed */ +#ifndef UTF8 int edit_print_string (WEdit * e, const char *s) +#else /* UTF8 */ +int edit_print_wstring (WEdit * e, mc_wchar_t *s) +#endif /* UTF8 */ { int i = 0; while (s[i]) - edit_execute_cmd (e, -1, (unsigned char) s[i++]); + edit_execute_cmd (e, -1, s[i++]); e->force |= REDRAW_COMPLETELY; edit_update_screen (e); return i; } +#ifdef UTF8 +int edit_print_string (WEdit * e, const char *s) +{ + int i; + mc_wchar_t *ws = mbstr_to_wchar(s); + i = edit_print_wstring (e, ws); + g_free(ws); + return i; +} + +#endif /* UTF8 */ int edit_printf (WEdit * e, const char *fmt, ...) { int i; @@ -2527,15 +2871,20 @@ void edit_mail_dialog (WEdit * edit) /* find first character of current word */ static int edit_find_word_start (WEdit *edit, long *word_start, int *word_len) { - int i, c, last; + int i; + mc_wint_t c, last; /* return if at begin of file */ if (edit->curs1 <= 0) return 0; - c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1); + c = edit_get_byte (edit, edit->curs1 - 1); /* return if not at end or in word */ +#ifndef UTF8 if (isspace (c) || !(isalnum (c) || c == '_')) +#else /* UTF8 */ + if (iswspace (c) || !(iswalnum (c) || c == '_')) +#endif /* UTF8 */ return 0; /* search start of word to be completed */ @@ -2545,11 +2894,19 @@ static int edit_find_word_start (WEdit * return 0; last = c; - c = (unsigned char) edit_get_byte (edit, edit->curs1 - i); + c = edit_get_byte (edit, edit->curs1 - i); +#ifndef UTF8 if (!(isalnum (c) || c == '_')) { +#else /* UTF8 */ + if (!(iswalnum (c) || c == '_')) { +#endif /* UTF8 */ /* return if word starts with digit */ +#ifndef UTF8 if (isdigit (last)) +#else /* UTF8 */ + if (iswdigit (last)) +#endif /* UTF8 */ return 0; *word_start = edit->curs1 - (i - 1); /* start found */ @@ -2582,7 +2939,7 @@ edit_collect_completions (WEdit *edit, l int *num) { int len, max_len = 0, i, skip; - char *bufpos; + mc_wchar_t *bufpos; /* collect max MAX_WORD_COMPLETIONS completions */ while (*num < MAX_WORD_COMPLETIONS) { @@ -2603,7 +2960,11 @@ edit_collect_completions (WEdit *edit, l buffers1[start >> S_EDIT_BUF_SIZE][start & M_EDIT_BUF_SIZE]; skip = 0; for (i = 0; i < *num; i++) { +#ifndef UTF8 if (strncmp +#else /* UTF8 */ + if (wcsncmp +#endif /* UTF8 */ (&compl[i].text[word_len], &bufpos[word_len], max (len, compl[i].len) - word_len) == 0) { skip = 1; @@ -2613,7 +2974,7 @@ edit_collect_completions (WEdit *edit, l if (skip) continue; - compl[*num].text = g_malloc (len + 1); + compl[*num].text = g_malloc ((len + 1) * sizeof(mc_wchar_t)); compl[*num].len = len; for (i = 0; i < len; i++) compl[*num].text[i] = *(bufpos + i); @@ -2646,6 +3007,9 @@ edit_completion_dialog (WEdit *edit, int WListbox *compl_list; unsigned int compl_dlg_h; /* completion dialog height */ unsigned int compl_dlg_w; /* completion dialog width */ +#ifdef UTF8 + char *mbtext; +#endif /* UTF8 */ /* calculate the dialog metrics */ compl_dlg_h = num_compl + 2; @@ -2682,8 +3046,16 @@ edit_completion_dialog (WEdit *edit, int add_widget (compl_dlg, compl_list); /* fill the listbox with the completions */ +#ifndef UTF8 for (i = 0; i < num_compl; i++) listbox_add_item (compl_list, 0, 0, compl[i].text, NULL); +#else /* UTF8 */ + for (i = 0; i < num_compl; i++) { + mbtext = wchar_to_mbstr(compl[i].text); + listbox_add_item (compl_list, 0, 0, mbtext, NULL); + g_free(mbtext); + } +#endif /* UTF8 */ /* pop up the dialog */ run_dlg (compl_dlg); @@ -2691,9 +3063,17 @@ edit_completion_dialog (WEdit *edit, int /* apply the choosen completion */ if (compl_dlg->ret_value == B_ENTER) { listbox_get_current (compl_list, &curr, NULL); - if (curr) + if (curr){ +#ifndef UTF8 for (curr += word_len; *curr; curr++) edit_insert (edit, *curr); +#else /* UTF8 */ + mc_wchar_t *wc, *wccurr = mbstr_to_wchar(curr); + for (wc = wccurr + word_len; *wc; wc++) + edit_insert (edit, *wc); + g_free(wccurr); +#endif /* UTF8 */ + } } /* destroy dialog before return */ @@ -2710,8 +3090,9 @@ edit_complete_word_cmd (WEdit *edit) { int word_len = 0, i, num_compl = 0, max_len; long word_start = 0; - char *bufpos; - char match_expr[MAX_REPL_LEN]; + mc_wchar_t *bufpos; + mc_wchar_t *match_expr; + char *mbmatch_expr; struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */ /* don't want to disturb another search */ @@ -2728,18 +3109,32 @@ edit_complete_word_cmd (WEdit *edit) /* prepare match expression */ bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE] [word_start & M_EDIT_BUF_SIZE]; - strncpy (match_expr, bufpos, word_len); + + match_expr = g_malloc((word_len + 14) * sizeof(mc_wchar_t)); +#ifndef UTF8 + match_expr = g_strdup_printf ("%.*s[a-zA-Z_0-9]+", word_len, bufpos); +#else /* UTF8 */ + wcsncpy (match_expr, bufpos, word_len); match_expr[word_len] = '\0'; - strcat (match_expr, "[a-zA-Z_0-9]+"); + wcscat (match_expr, L"[a-zA-Z_0-9]+"); +#endif /* UTF8 */ /* init search: backward, regexp, whole word, case sensitive */ edit_set_search_parameters (0, 1, 1, 1, 1); /* collect the possible completions */ /* start search from curs1 down to begin of file */ +#ifndef UTF8 max_len = edit_collect_completions (edit, word_start, word_len, match_expr, (struct selection *) &compl, &num_compl); +#else /* UTF8 */ + mbmatch_expr = wchar_to_mbstr(match_expr); + max_len = + edit_collect_completions (edit, word_start, word_len, mbmatch_expr, + (struct selection *) &compl, &num_compl); + g_free(mbmatch_expr); +#endif /* UTF8 */ if (num_compl > 0) { /* insert completed word if there is only one match */ @@ -2762,6 +3157,9 @@ edit_complete_word_cmd (WEdit *edit) } /* release memory before return */ + + g_free (match_expr); + for (i = 0; i < num_compl; i++) g_free (compl[i].text); --- edit/editdraw.c +++ edit/editdraw.c @@ -48,7 +48,7 @@ static void status_string (WEdit * edit, char *s, int w, int fill) { - char byte_str[16]; + char byte_str[32]; /* * If we are at the end of file, print , @@ -56,9 +56,14 @@ static void status_string (WEdit * edit, * as decimal and as hex. */ if (edit->curs1 < edit->last_byte) { - unsigned char cur_byte = edit_get_byte (edit, edit->curs1); + mc_wchar_t cur_byte = edit_get_byte (edit, edit->curs1); +#ifndef UTF8 g_snprintf (byte_str, sizeof(byte_str), "%c %3d 0x%02X", is_printable(cur_byte) ? cur_byte : '.', +#else /* UTF8 */ + g_snprintf (byte_str, sizeof(byte_str), "%lc %3d 0x%02X", + iswprint(cur_byte) ? cur_byte : '.', +#endif /* UTF8 */ cur_byte, cur_byte); } else { @@ -175,13 +180,19 @@ void edit_scroll_screen_over_cursor (WEd #define lowlevel_set_color(x) attrset(MY_COLOR_PAIR(color)) #endif +struct line_s { + mc_wchar_t ch; + unsigned int style; +}; + static void print_to_widget (WEdit *edit, long row, int start_col, int start_col_real, - long end_col, unsigned int line[]) + long end_col, struct line_s line[]) { - unsigned int *p; + struct line_s *p; + + int x; - int x = start_col_real + EDIT_TEXT_HORIZONTAL_OFFSET; int x1 = start_col + EDIT_TEXT_HORIZONTAL_OFFSET; int y = row + EDIT_TEXT_VERTICAL_OFFSET; @@ -189,13 +200,22 @@ print_to_widget (WEdit *edit, long row, edit_move (x1, y); hline (' ', end_col + 1 - EDIT_TEXT_HORIZONTAL_OFFSET - x1); - edit_move (x + FONT_OFFSET_X, y + FONT_OFFSET_Y); p = line; - while (*p) { - int style = *p & 0xFF00; - int textchar = *p & 0xFF; - int color = *p >> 16; + while (start_col_real < 0) { + if (!p->ch) + return; + p++; + start_col_real++; + } + + x = start_col_real + EDIT_TEXT_HORIZONTAL_OFFSET; + edit_move (x + FONT_OFFSET_X, y + FONT_OFFSET_Y); + + while (p->ch) { + int style = p->style & 0xFF00; + mc_wchar_t textchar = p->ch; + int color = p->style >> 16; if (style & MOD_ABNORMAL) { /* Non-printable - use black background */ @@ -209,8 +229,7 @@ print_to_widget (WEdit *edit, long row, } else { lowlevel_set_color (color); } - - addch (textchar); + SLsmg_write_char(textchar); p++; } } @@ -220,11 +239,11 @@ static void edit_draw_this_line (WEdit *edit, long b, long row, long start_col, long end_col) { - static unsigned int line[MAX_LINE_LEN]; - unsigned int *p = line; + struct line_s line[MAX_LINE_LEN]; + struct line_s *p = line; long m1 = 0, m2 = 0, q, c1, c2; int col, start_col_real; - unsigned int c; + mc_wint_t c; int color; int i, book_mark = -1; @@ -246,66 +265,96 @@ edit_draw_this_line (WEdit *edit, long b if (row <= edit->total_lines - edit->start_line) { while (col <= end_col - edit->start_col) { - *p = 0; + p->ch = 0; + p->style = 0; if (q == edit->curs1) - *p |= MOD_CURSOR; + p->style |= MOD_CURSOR; if (q >= m1 && q < m2) { if (column_highlighting) { int x; x = edit_move_forward3 (edit, b, 0, q); if (x >= c1 && x < c2) - *p |= MOD_MARKED; + p->style |= MOD_MARKED; } else - *p |= MOD_MARKED; + p->style |= MOD_MARKED; } if (q == edit->bracket) - *p |= MOD_BOLD; + p->style |= MOD_BOLD; if (q >= edit->found_start && q < edit->found_start + edit->found_len) - *p |= MOD_BOLD; + p->style |= MOD_BOLD; c = edit_get_byte (edit, q); /* we don't use bg for mc - fg contains both */ if (book_mark == -1) { edit_get_syntax_color (edit, q, &color); - *p |= color << 16; + p->style |= color << 16; } else { - *p |= book_mark << 16; + p->style |= book_mark << 16; } q++; switch (c) { case '\n': col = end_col - edit->start_col + 1; /* quit */ - *(p++) |= ' '; + p->ch = ' '; + p++; break; case '\t': i = TAB_SIZE - ((int) col % TAB_SIZE); - *p |= ' '; - c = *(p++) & ~MOD_CURSOR; + p->ch = ' '; + c = p->style & ~MOD_CURSOR; + p++; col += i; - while (--i) - *(p++) = c; + while (--i) { + p->ch = ' '; p->style = c; + p++; + } break; default: c = convert_to_display_c (c); /* Caret notation for control characters */ if (c < 32) { - *(p++) = '^' | MOD_ABNORMAL; - *(p++) = (c + 0x40) | MOD_ABNORMAL; + p->ch = '^'; + p->style = MOD_ABNORMAL; + p++; + p->ch = c + 0x40; + p->style = MOD_ABNORMAL; col += 2; break; } if (c == 127) { - *(p++) = '^' | MOD_ABNORMAL; - *(p++) = '?' | MOD_ABNORMAL; + p->ch = '^'; + p->style = MOD_ABNORMAL; + p++; + p->ch = '?'; + p->style = MOD_ABNORMAL; + p++; col += 2; break; } - if (is_printable (c)) { - *(p++) |= c; +#ifndef UTF8 + if (is_printable (c) +#else /* UTF8 */ + if (iswprint (c) +#ifdef __STDC_ISO_10646__ + && (c < BINARY_CHAR_OFFSET || c >= (BINARY_CHAR_OFFSET + 256)) +#endif +#endif /* UTF8 */ + ) { + p->ch = c; + p++; + +#ifdef UTF8 + i = wcwidth(c); + if (i > 1) { + col += i - 1; + } +#endif /* UTF8 */ } else { - *(p++) = '.' | MOD_ABNORMAL; + p->ch = '.'; + p->style = MOD_ABNORMAL; + p++; } col++; break; @@ -315,7 +364,7 @@ edit_draw_this_line (WEdit *edit, long b } else { start_col_real = start_col = 0; } - *p = 0; + p->ch = 0; print_to_widget (edit, row, start_col, start_col_real, end_col, line); } --- edit/editkeys.c +++ edit/editkeys.c @@ -200,10 +200,10 @@ static long const common_key_map[] = { * 'command' is one of the editor commands from editcmddef.h. */ int -edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch) +edit_translate_key (WEdit *edit, long x_key, int *cmd, mc_wint_t *ch) { int command = -1; - int char_for_insertion = -1; + mc_wint_t char_for_insertion = -1; int i = 0; static const long *key_map; @@ -280,9 +280,30 @@ edit_translate_key (WEdit *edit, long x_ /* an ordinary insertable character */ if (x_key < 256) { int c = convert_from_input_c (x_key); - +#ifdef UTF8 + mbstate_t mbs; + int res; + mc_wchar_t wc; + + memset (&mbs, 0, sizeof (mbs)); + + if (edit->charpoint >= MB_CUR_MAX) edit->charpoint = 0; + + edit->charbuf[edit->charpoint++] = c; + + res = mbrtowc(&wc, edit->charbuf, edit->charpoint, &mbs); + if (res < 0) { + if (res != -2) edit->charpoint = 0; /* broken multibyte char, skip */ + return 0; + } + edit->charpoint = 0; + + if (iswprint (wc)) { + char_for_insertion = wc; +#else if (is_printable (c)) { char_for_insertion = c; +#endif /* UTF8 */ goto fin; } } @@ -321,7 +342,7 @@ edit_translate_key (WEdit *edit, long x_ *cmd = command; *ch = char_for_insertion; - if ((command == -1 || command == 0) && char_for_insertion == -1) { + if ((command == -1 || command == 0) && char_for_insertion == (mc_wint_t)-1) { /* unchanged, key has no function here */ return 0; } --- edit/wordproc.c +++ edit/wordproc.c @@ -24,7 +24,12 @@ #define tab_width option_tab_spacing +#ifndef UTF8 #define NO_FORMAT_CHARS_START "-+*\\,.;:&>" +#else /* UTF8 */ +#define NO_FORMAT_CHARS_START L"-+*\\,.;:&>" +#endif /* UTF8 */ + #define FONT_MEAN_WIDTH 1 static long @@ -41,14 +46,21 @@ line_start (WEdit *edit, long line) p = edit_move_forward (edit, p, line - l, 0); p = edit_bol (edit, p); + +#ifndef UTF8 while (strchr ("\t ", edit_get_byte (edit, p))) +#else /* UTF8 */ + while (wcschr (L"\t ", edit_get_byte (edit, p))) +#endif /* UTF8 */ + p++; return p; } static int bad_line_start (WEdit * edit, long p) { - int c; + mc_wint_t c; + c = edit_get_byte (edit, p); if (c == '.') { /* `...' is acceptable */ if (edit_get_byte (edit, p + 1) == '.') @@ -62,7 +74,13 @@ static int bad_line_start (WEdit * edit, return 0; /* `---' is acceptable */ return 1; } + +#ifndef UTF8 if (strchr (NO_FORMAT_CHARS_START, c)) +#else /* UTF8 */ + if (wcschr (NO_FORMAT_CHARS_START, c)) +#endif /* UTF8 */ + return 1; return 0; } @@ -115,33 +133,37 @@ end_paragraph (WEdit *edit, int force) i - edit->curs_line, 0)); } -static unsigned char * +static mc_wchar_t * get_paragraph (WEdit *edit, long p, long q, int indent, int *size) { - unsigned char *s, *t; + mc_wchar_t *s, *t; #if 0 - t = g_malloc ((q - p) + 2 * (q - p) / option_word_wrap_line_length + - 10); + t = g_malloc (((q - p) + 2 * (q - p) / option_word_wrap_line_length + + 10) * sizeof(mc_wchar_t)); #else - t = g_malloc (2 * (q - p) + 100); + t = g_malloc ((2 * (q - p) + 100) * sizeof(mc_wchar_t)); #endif if (!t) return 0; for (s = t; p < q; p++, s++) { if (indent) if (edit_get_byte (edit, p - 1) == '\n') +#ifndef UTF8 while (strchr ("\t ", edit_get_byte (edit, p))) +#else /* UTF8 */ + while (wcschr (L"\t ", edit_get_byte (edit, p))) +#endif /* UTF8 */ p++; *s = edit_get_byte (edit, p); } - *size = (unsigned long) s - (unsigned long) t; + *size = s - t; t[*size] = '\n'; return t; } -static void strip_newlines (unsigned char *t, int size) +static void strip_newlines (mc_wchar_t *t, int size) { - unsigned char *p = t; + mc_wchar_t *p = t; while (size--) { *p = *p == '\n' ? ' ' : *p; p++; @@ -158,7 +180,7 @@ static inline int next_tab_pos (int x) { return x += tab_width - x % tab_width; } -static int line_pixel_length (unsigned char *t, long b, int l) +static int line_pixel_length (mc_wchar_t *t, long b, int l) { int x = 0, c, xn = 0; for (;;) { @@ -182,7 +204,7 @@ static int line_pixel_length (unsigned c } /* find the start of a word */ -static int next_word_start (unsigned char *t, int q, int size) +static int next_word_start (mc_wchar_t *t, int q, int size) { int i; for (i = q;; i++) { @@ -203,13 +225,13 @@ static int next_word_start (unsigned cha } /* find the start of a word */ -static int word_start (unsigned char *t, int q, int size) +static int word_start (mc_wchar_t *t, int q, int size) { int i = q; if (t[q] == ' ' || t[q] == '\t') return next_word_start (t, q, size); for (;;) { - int c; + mc_wchar_t c; if (!i) return -1; c = t[i - 1]; @@ -222,7 +244,7 @@ static int word_start (unsigned char *t, } /* replaces ' ' with '\n' to properly format a paragraph */ -static void format_this (unsigned char *t, int size, int indent) +static void format_this (mc_wchar_t *t, int size, int indent) { int q = 0, ww; strip_newlines (t, size); @@ -250,7 +272,7 @@ static void format_this (unsigned char * } } -static void replace_at (WEdit * edit, long q, int c) +static void replace_at (WEdit * edit, long q, mc_wint_t c) { edit_cursor_move (edit, q - edit->curs1); edit_delete (edit); @@ -258,18 +280,27 @@ static void replace_at (WEdit * edit, lo } /* replaces a block of text */ -static void put_paragraph (WEdit * edit, unsigned char *t, long p, long q, int indent, int size) +static void put_paragraph (WEdit * edit, mc_wchar_t *t, long p, long q, int indent, int size) { long cursor; - int i, c = 0; + int i; + mc_wint_t c = 0; cursor = edit->curs1; if (indent) +#ifndef UTF8 while (strchr ("\t ", edit_get_byte (edit, p))) +#else /* UTF8 */ + while (wcschr (L"\t ", edit_get_byte (edit, p))) +#endif /* UTF8 */ p++; for (i = 0; i < size; i++, p++) { if (i && indent) { if (t[i - 1] == '\n' && c == '\n') { +#ifndef UTF8 while (strchr ("\t ", edit_get_byte (edit, p))) +#else /* UTF8 */ + while (wcschr (L"\t ", edit_get_byte (edit, p))) +#endif /* UTF8 */ p++; } else if (t[i - 1] == '\n') { long curs; @@ -281,7 +312,11 @@ static void put_paragraph (WEdit * edit, p = edit->curs1; } else if (c == '\n') { edit_cursor_move (edit, p - edit->curs1); +#ifndef UTF8 while (strchr ("\t ", edit_get_byte (edit, p))) { +#else /* UTF8 */ + while (wcschr (L"\t ", edit_get_byte (edit, p))) { +#endif /* UTF8 */ edit_delete (edit); if (cursor > edit->curs1) cursor--; @@ -314,7 +349,7 @@ format_paragraph (WEdit *edit, int force { long p, q; int size; - unsigned char *t; + mc_wchar_t *t; int indent = 0; if (option_word_wrap_line_length < 2) return; @@ -324,17 +359,25 @@ format_paragraph (WEdit *edit, int force q = end_paragraph (edit, force); indent = test_indent (edit, p, q); t = get_paragraph (edit, p, q, indent, &size); - if (!t) + if (!t) return; if (!force) { int i; +#ifndef UTF8 if (strchr (NO_FORMAT_CHARS_START, *t)) { +#else /* UTF8 */ + if (wcschr (NO_FORMAT_CHARS_START, *t)) { +#endif /* UTF8 */ g_free (t); return; } for (i = 0; i < size - 1; i++) { if (t[i] == '\n') { +#ifndef UTF8 if (strchr (NO_FORMAT_CHARS_START "\t ", t[i + 1])) { +#else /* UTF8 */ + if (wcschr (NO_FORMAT_CHARS_START "\t", t[i + 1])) { +#endif /* UTF8 */ g_free (t); return; } --- src/util.c +++ src/util.c @@ -98,6 +98,44 @@ mbstrlen (const char *str) return strlen (str); } +#ifdef UTF8 +wchar_t * +mbstr_to_wchar (const char *str) +{ + int len = mbstrlen(str); + wchar_t *buf = g_malloc((len+1) * sizeof(wchar_t)); + mbstate_t mbs; + memset (&mbs, 0, sizeof (mbs)); + mbsrtowcs (buf, &str, len, &mbs); + buf[len] = 0; + return buf; +} + +char * +wchar_to_mbstr (const wchar_t *wstr) +{ + mbstate_t mbs; + const wchar_t *wstr2; + char * string; + int len; + + memset (&mbs, 0, sizeof (mbs)); + wstr2 = wstr; + len = wcsrtombs(NULL, &wstr2, 0, &mbs); + if (len <= 0) + return NULL; + + string = g_malloc(len + 1); + + wstr2 = wstr; + wcsrtombs(string, &wstr2, len, &mbs); + string[len] = 0; + return string; +} +#endif + + + int is_printable (int c) { --- src/util.h +++ src/util.h @@ -48,6 +48,8 @@ char *get_group (int); char *get_owner (int); int mbstrlen (const char *); +wchar_t *mbstr_to_wchar (const char *); +char *wchar_to_mbstr (const wchar_t *); #define MAX_I18NTIMELENGTH 14 #define MIN_I18NTIMELENGTH 10 --- src/view.c +++ src/view.c @@ -876,7 +876,11 @@ view_display_clean (WView *view, int hei widget_erase ((Widget *) view); } +#ifndef UTF8 #define view_add_character(view,c) addch (c) +#else /* UTF8 */ +#define view_add_character(view,c) SLsmg_write_char(c) +#endif /* UTF8 */ #define view_add_one_vline() one_vline() #define view_add_string(view,s) addstr (s) #define view_gotoyx(v,r,c) widget_move (v,r,c) @@ -1089,6 +1093,13 @@ display (WView *view) if (view->growing_buffer && from == view->last_byte) get_byte (view, from); for (; row < height && from < view->last_byte; from++) { +#ifdef UTF8 + mbstate_t mbs; + char mbbuf[MB_LEN_MAX]; + int mblen; + wchar_t wc; + +#endif /* UTF8 */ c = get_byte (view, from); if ((c == '\n') || (col >= width && view->wrap_mode)) { col = frame_shift; @@ -1102,7 +1113,39 @@ display (WView *view) col = ((col - frame_shift) / 8) * 8 + 8 + frame_shift; continue; } +#ifndef UTF8 if (view->viewer_nroff_flag && c == '\b') { + +#else /* UTF8 */ + mblen = 1; + mbbuf[0] = c; + + while (mblen < MB_LEN_MAX) { + int res; + memset (&mbs, 0, sizeof (mbs)); + res = mbrtowc(&wc, mbbuf, mblen, &mbs); + if (res <= 0 && res != -2) { + wc = '.'; + mblen = 1; + break; + } + if (res == mblen) + break; + + mbbuf[mblen] = get_byte (view, from + mblen); + mblen++; + } + + if (mblen == MB_LEN_MAX) { + wc = '.'; + mblen = 1; + } + + from += mblen - 1; + + + if (view->viewer_nroff_flag && wc == '\b') { +#endif /* UTF8 */ int c_prev; int c_next; @@ -1139,12 +1182,24 @@ display (WView *view) && col < width - view->start_col) { view_gotoyx (view, row, col + view->start_col); +#ifndef UTF8 c = convert_to_display_c (c); - if (!is_printable (c)) c = '.'; - view_add_character (view, c); +#else /* UTF8 */ + wc = convert_to_display_c (wc); + if (!iswprint (wc)) + wc = '.'; + view_add_character (view, wc); + + { + int cw = wcwidth(wc); + if (cw > 1) + col+= cw - 1; + } +#endif /* UTF8 */ + } col++; if (boldflag != MARK_NORMAL) { --- src/widget.c +++ src/widget.c @@ -33,6 +33,9 @@ #include #include "global.h" #include "tty.h" +#ifdef UTF8 +#include +#endif /* UTF8 */ #include "color.h" #include "mouse.h" #include "dlg.h" @@ -765,13 +768,70 @@ static void draw_history_button (WInput /* Pointer to killed data */ static char *kill_buffer = 0; +#ifdef UTF8 +static int +charpos(WInput *in, int idx) +{ + int i, pos, l; + mbstate_t mbs; + memset (&mbs, 0, sizeof (mbs)); + i = 0; + pos = 0; + int len = strlen(in->buffer); + + while (in->buffer[pos]) { + if (i == idx) + return pos; + l = mbrlen(in->buffer + pos, len - pos, &mbs); + if (l <= 0) + return pos; + pos+=l; + i++; + }; + return pos; +} + +static int +charcolumn(WInput *in, int idx) +{ + int i, pos, l, width; + mbstate_t mbs; + memset (&mbs, 0, sizeof (mbs)); + i = 0; + pos = 0; width = 0; + int len = strlen(in->buffer); + + while (in->buffer[pos]) { + wchar_t wc; + if (i == idx) + return width; + l = mbrtowc(&wc, in->buffer + pos, len - pos, &mbs); + if (l <= 0) + return width; + pos += l; width += wcwidth(wc); + i++; + }; + return width; +} +#else +#define charpos(in, idx) (idx) +#define charcolumn(in, idx) (idx) +#endif /* UTF8 */ + void update_input (WInput *in, int clear_first) { int has_history = 0; int i, j; - unsigned char c; int buf_len = mbstrlen (in->buffer); +#ifndef UTF8 + unsigned char c; +#else /* UTF8 */ + wchar_t c; + mbstate_t mbs; + memset (&mbs, 0, sizeof (mbs)); + +#endif /* UTF8 */ if (should_show_history_button (in)) has_history = HISTORY_BUTTON_WIDTH; @@ -781,7 +841,7 @@ update_input (WInput *in, int clear_firs /* Make the point visible */ if ((in->point < in->first_shown) || - (in->point >= in->first_shown+in->field_len - has_history)){ + (charcolumn(in, in->point) >= charcolumn(in, 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; @@ -800,15 +860,32 @@ update_input (WInput *in, int clear_firs for (i = 0; i < in->field_len - has_history; i++) addch (' '); widget_move (&in->widget, 0, 0); + +#ifndef UTF8 + 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) +#else /* UTF8 */ + for (i = 0, j = in->first_shown; (i < in->field_len - has_history) && (j < buf_len); i++,j++){ + char * chp = in->buffer + charpos(in,j); + size_t res = mbrtowc(&c, chp, strlen(chp), &mbs); + c = (res && iswprint (c)) ? 0 : '.'; +#endif /* UTF8 */ + if (in->is_password) c = '*'; +#ifndef UTF8 addch (c); +#else /* UTF8 */ + if (c) { + addch (c); + } + else + SLsmg_write_nchars (chp, res); +#endif /* UTF8 */ } - widget_move (&in->widget, 0, in->point - in->first_shown); + widget_move (&in->widget, 0, charcolumn(in, in->point) - charcolumn(in, in->first_shown)); if (clear_first) in->first = 0; @@ -1138,39 +1215,86 @@ new_input (WInput *in) in->need_push = 1; 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 point) +{ + int i, pos, len; + int str_len = mbstrlen (in->buffer); + if (point >= str_len) return; + + pos = charpos(in,point); + len = charpos(in,point + 1) - pos; + + for (i = pos; in->buffer [i + len - 1]; i++) + in->buffer [i] = in->buffer [i + len]; +} + static int insert_char (WInput *in, int c_code) { int i; +#ifdef UTF8 + mbstate_t mbs; + int res; + + memset (&mbs, 0, sizeof (mbs)); +#else + in->charpoint = 0; +#endif /* UTF8 */ if (c_code == -1) return 0; +#ifdef UTF8 + if (in->charpoint >= MB_CUR_MAX) return 1; + + in->charbuf[in->charpoint++] = c_code; + + res = mbrlen(in->charbuf, in->charpoint, &mbs); + if (res < 0) { + if (res != -2) in->charpoint = 0; /* broken multibyte char, skip */ + return 1; + } + +#endif /* UTF8 */ in->need_push = 1; - if (strlen (in->buffer)+1 == in->current_max_len){ + if (strlen (in->buffer) + 1 + in->charpoint >= in->current_max_len){ /* Expand the buffer */ - char *narea = g_malloc (in->current_max_len + in->field_len); + char *narea = g_malloc (in->current_max_len + in->field_len + in->charpoint); if (narea){ char *p = in->buffer; - strcpy (narea, in->buffer); in->buffer = narea; - in->current_max_len += in->field_len; + in->current_max_len += in->field_len + in->charpoint; g_free (p); } } +#ifndef UTF8 if (strlen (in->buffer)+1 < in->current_max_len){ int 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; +#else /* UTF8 */ + if (strlen (in->buffer) + in->charpoint < in->current_max_len){ + int ins_point = charpos(in,in->point); /* bytes from begin */ + /* move chars */ + int rest_bytes = strlen (in->buffer + ins_point); + + for (i = rest_bytes; i >= 0; i--) + in->buffer [ins_point+i+in->charpoint] = in->buffer [ins_point+i]; + + memcpy(in->buffer + ins_point, in->charbuf, in->charpoint); +#endif /* UTF8 */ in->point++; } + in->charpoint = 0; return 1; } @@ -1178,12 +1302,14 @@ 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 = mbstrlen (in->buffer); + in->charpoint = 0; } static void @@ -1191,37 +1317,92 @@ backward_char (WInput *in) { if (in->point) in->point--; + in->charpoint = 0; } static void forward_char (WInput *in) { - if (in->buffer [in->point]) + if (in->buffer [charpos(in,in->point)]) in->point++; + in->charpoint = 0; } static void forward_word (WInput *in) { +#ifndef UTF8 unsigned char *p = in->buffer+in->point; - while (*p && (isspace (*p) || ispunct (*p))) p++; while (*p && isalnum (*p)) p++; in->point = p - in->buffer; +#else /* UTF8 */ + mbstate_t mbs; + int len = mbstrlen (in->buffer); + memset (&mbs, 0, sizeof (mbs)); + + while (in->point < len) { + wchar_t c; + char *p = in->buffer + charpos(in,in->point); + size_t res = mbrtowc(&c, p, strlen(p), &mbs); + if (res <= 0 || !(iswspace (c) || iswpunct (c))) + break; + in->point++; + } + + memset (&mbs, 0, sizeof (mbs)); + + while (in->point < len) { + wchar_t c; + char *p = in->buffer + charpos(in,in->point); + size_t res = mbrtowc(&c, p, strlen(p), &mbs); + if (res <= 0 || !iswalnum (c)) + break; + in->point++; + } + + in->charpoint = 0; +#endif /* UTF8 */ } static void backward_word (WInput *in) { +#ifndef UTF8 unsigned char *p = in->buffer+in->point; - while (p-1 > in->buffer-1 && (isspace (*(p-1)) || ispunct (*(p-1)))) p--; while (p-1 > in->buffer-1 && isalnum (*(p-1))) p--; in->point = p - in->buffer; +#else /* UTF8 */ + mbstate_t mbs; + + memset (&mbs, 0, sizeof (mbs)); + while (in->point > 0) { + wchar_t c; + char *p = in->buffer + charpos(in,in->point); + size_t res = mbrtowc(&c, p, strlen(p), &mbs); + if (*p && (res <= 0 || !(iswspace (c) || iswpunct (c)))) + break; + in->point--; + } + + memset (&mbs, 0, sizeof (mbs)); + + while (in->point > 0) { + wchar_t c; + char *p = in->buffer + charpos(in,in->point); + size_t res = mbrtowc(&c, p, strlen(p), &mbs); + if (*p && (res <= 0 || !iswalnum (c))) + break; + in->point--; + } + + in->charpoint = 0; +#endif /* UTF8 */ } static void @@ -1254,8 +1435,9 @@ backward_delete (WInput *in) if (!in->point) return; - for (i = in->point; in->buffer [i-1]; i++) - in->buffer [i-1] = in->buffer [i]; + + move_buffer_backward(in, in->point - 1); + in->charpoint = 0; in->need_push = 1; in->point--; } @@ -1263,10 +1445,8 @@ backward_delete (WInput *in) static void delete_char (WInput *in) { - int i; - - for (i = in->point; in->buffer [i]; i++) - in->buffer [i] = in->buffer [i+1]; + move_buffer_backward(in, in->point); + in->charpoint = 0; in->need_push = 1; } @@ -1282,6 +1462,9 @@ copy_region (WInput *in, int x_first, in if (kill_buffer) g_free (kill_buffer); + first=charpos(in,first); + last=charpos(in,last); + kill_buffer = g_malloc (last-first + 1); strncpy (kill_buffer, in->buffer+first, last-first); kill_buffer [last-first] = 0; @@ -1295,7 +1478,9 @@ delete_region (WInput *in, int x_first, in->point = first; in->mark = first; - strcpy (&in->buffer [first], &in->buffer [last]); + size_t len = strlen (&in->buffer [charpos(in,last)]) + 1; + memmove (&in->buffer [charpos(in,first)], &in->buffer [charpos(in,last)], len); + in->charpoint = 0; in->need_push = 1; } @@ -1312,6 +1497,7 @@ 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; } static void @@ -1327,6 +1513,7 @@ back_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; } static void @@ -1355,17 +1542,21 @@ 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 = charpos(in,in->point); if (kill_buffer) 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 @@ -1375,9 +1566,10 @@ assign_text (WInput *in, char *text) 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->point = mbstrlen (in->buffer); in->mark = 0; in->need_push = 1; + in->charpoint = 0; } static void @@ -1499,6 +1691,7 @@ port_region_marked_for_delete (WInput *i *in->buffer = 0; in->point = 0; in->first = 0; + in->charpoint = 0; } int @@ -1527,7 +1720,11 @@ handle_char (WInput *in, int c_code) } } if (!input_map [i].fn){ +#ifndef UTF8 if (c_code > 255 || !is_printable (c_code)) +#else /* UTF8 */ + if (c_code > 255) +#endif /* UTF8 */ return 0; if (in->first){ port_region_marked_for_delete (in); @@ -1561,6 +1758,9 @@ input_set_point (WInput *in, int pos) if (pos != in->point) free_completions (in); in->point = pos; +#ifdef UTF8 + in->charpoint = 0; +#endif /* UTF8 */ update_input (in, 1); } @@ -1606,7 +1806,7 @@ input_callback (WInput *in, int Msg, int update_input (in, 0); break; case WIDGET_CURSOR: - widget_move (&in->widget, 0, in->point - in->first_shown); + widget_move (&in->widget, 0, charcolumn(in, in->point) - charcolumn(in, in->first_shown)); return 1; } @@ -1623,7 +1823,7 @@ input_event (Gpm_Event * event, WInput * && should_show_history_button (in)) { do_show_hist (in); } else { - in->point = strlen (in->buffer); + in->point = mbstrlen (in->buffer); if (event->x - in->first_shown - 1 < in->point) in->point = event->x - in->first_shown - 1; if (in->point < 0) @@ -1681,7 +1881,9 @@ input_new (int y, int x, int color, int in->is_password = 0; strcpy (in->buffer, def_text); - in->point = strlen (in->buffer); + + in->point = mbstrlen (in->buffer); + in->charpoint = 0; return in; } --- src/widget.h +++ src/widget.h @@ -64,16 +64,20 @@ char *show_hist (Hist *history, int widg 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 (mb chars)*/ + int mark; /* The mark position (mb chars)*/ + int first_shown; /* Index of the first shown character (mb chars)*/ + int current_max_len; /* Maximum length of input line (bytes)*/ + int field_len; /* Length of the editing field (mb chars)*/ int color; /* color used */ int first; /* Is first keystroke? */ int disable_update; /* Do we want to skip updates? */ int is_password; /* Is this a password input line? */ unsigned char *buffer; /* pointer to editing buffer */ +#ifdef UTF8 + unsigned char charbuf[MB_LEN_MAX]; +#endif /* UTF8 */ + int charpoint; Hist *history; /* The history */ int need_push; /* need to push the current Input on hist? */ char **completions; /* Possible completions array */