updated on Sat Jan 14 16:01:55 UTC 2012
[aur-mirror.git] / mc-suse / mc-utf8.patch
blob535b4a6c36c9eacf2748d68daa04e88ec3a960a4
1 --- mc-4.6.2-pre1/acinclude.m4
2 +++ mc-4.6.2-pre1/acinclude.m4
3 @@ -399,14 +399,14 @@
4 fi
6 dnl Unless external S-Lang was requested, reject S-Lang with UTF-8 hacks
7 - if test x$with_screen = xslang; then
8 - :
9 - m4_if([$1], strict, ,
10 - [AC_CHECK_LIB([slang], [SLsmg_write_nwchars],
11 - [AC_MSG_WARN([Rejecting S-Lang with UTF-8 support, \
12 -it's not fully supported yet])
13 - with_screen=mcslang])])
14 - fi
15 +dnl if test x$with_screen = xslang; then
16 +dnl :
17 +dnl m4_if([$1], strict, ,
18 +dnl [AC_CHECK_LIB([slang], [SLsmg_write_nwchars],
19 +dnl [AC_MSG_WARN([Rejecting S-Lang with UTF-8 support, \
20 +dnl it's not fully supported yet])
21 +dnl with_screen=mcslang])])
22 +dnl fi
24 if test x$with_screen = xslang; then
25 AC_DEFINE(HAVE_SYSTEM_SLANG, 1,
26 --- mc-4.6.2-pre1/edit/edit-widget.h
27 +++ mc-4.6.2-pre1/edit/edit-widget.h
28 @@ -30,6 +30,11 @@
29 long command;
30 } edit_key_map_type;
32 +struct action {
33 + mc_wchar_t ch;
34 + long flags;
35 +};
37 struct WEdit {
38 Widget widget;
40 @@ -42,8 +47,17 @@
41 /* dynamic buffers and cursor position for editor: */
42 long curs1; /* position of the cursor from the beginning of the file. */
43 long curs2; /* position from the end of the file */
44 +#ifndef UTF8
45 unsigned char *buffers1[MAXBUFF + 1]; /* all data up to curs1 */
46 unsigned char *buffers2[MAXBUFF + 1]; /* all data from end of file down to curs2 */
47 +#else /* UTF8 */
48 + mc_wchar_t *buffers1[MAXBUFF + 1]; /* all data up to curs1 */
49 + mc_wchar_t *buffers2[MAXBUFF + 1]; /* all data from end of file down to curs2 */
51 + unsigned char charbuf[MB_LEN_MAX];
52 + int charpoint;
53 +#endif /* UTF8 */
56 /* search variables */
57 long search_start; /* First character to start searching from */
58 @@ -87,7 +101,7 @@
60 /* undo stack and pointers */
61 unsigned long stack_pointer;
62 - long *undo_stack;
63 + struct action *undo_stack;
64 unsigned long stack_size;
65 unsigned long stack_size_mask;
66 unsigned long stack_bottom;
67 --- mc-4.6.2-pre1/edit/edit.c
68 +++ mc-4.6.2-pre1/edit/edit.c
69 @@ -102,7 +102,11 @@
71 static void user_menu (WEdit *edit);
73 +#ifndef UTF8
74 int edit_get_byte (WEdit * edit, long byte_index)
75 +#else
76 +mc_wchar_t edit_get_byte (WEdit * edit, long byte_index)
77 +#endif
79 unsigned long p;
80 if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0)
81 @@ -131,7 +135,7 @@
83 edit->curs1 = 0;
84 edit->curs2 = 0;
85 - edit->buffers2[0] = g_malloc (EDIT_BUF_SIZE);
86 + edit->buffers2[0] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
90 @@ -156,7 +160,7 @@
93 if (!edit->buffers2[buf2])
94 - edit->buffers2[buf2] = g_malloc (EDIT_BUF_SIZE);
95 + edit->buffers2[buf2] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
97 mc_read (file,
98 (char *) edit->buffers2[buf2] + EDIT_BUF_SIZE -
99 @@ -166,7 +170,7 @@
100 for (buf = buf2 - 1; buf >= 0; buf--) {
101 /* edit->buffers2[0] is already allocated */
102 if (!edit->buffers2[buf])
103 - edit->buffers2[buf] = g_malloc (EDIT_BUF_SIZE);
104 + edit->buffers2[buf] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
105 mc_read (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE);
108 @@ -239,9 +243,44 @@
110 int c;
111 long i = 0;
112 - while ((c = fgetc (f)) >= 0) {
113 +#ifndef UTF8
114 + while ((c = fgetc (f)) != EOF) {
115 edit_insert (edit, c);
116 i++;
117 +#else /* UTF8 */
118 + unsigned char buf[MB_LEN_MAX];
119 + int charpos = 0;
120 + mbstate_t mbs;
122 + while ((c = fgetc (f)) != EOF) {
123 + mc_wchar_t wc;
124 + int size;
125 + int j;
127 + buf[charpos++] = c;
129 + memset (&mbs, 0, sizeof (mbs));
130 + size = mbrtowc(&wc, (char *)buf, charpos, &mbs);
132 + if (size == -2)
133 + continue; /* incomplete */
135 + else if (size >= 0) {
136 + edit_insert (edit, wc);
137 + i++;
138 + charpos = 0;
139 + continue;
141 + else {
143 + /* invalid */
144 +#ifdef __STDC_ISO_10646__
145 + for (j=0; j<charpos; j++)
146 + edit_insert (edit, BINARY_CHAR_OFFSET + (mc_wchar_t)buf[j]);
147 +#endif
148 + charpos = 0;
150 +#endif /* UTF8 */
152 return i;
154 @@ -249,9 +288,32 @@
155 long edit_write_stream (WEdit * edit, FILE * f)
157 long i;
158 +#ifndef UTF8
159 for (i = 0; i < edit->last_byte; i++)
160 if (fputc (edit_get_byte (edit, i), f) < 0)
161 break;
162 +#else /* UTF8 */
163 + for (i = 0; i < edit->last_byte; i++) {
164 + mc_wchar_t wc = edit_get_byte (edit, i);
165 + int res;
166 + char tmpbuf[MB_LEN_MAX];
167 + mbstate_t mbs;
169 + memset (&mbs, 0, sizeof (mbs));
171 +#ifdef __STDC_ISO_10646__
172 + if (wc >= BINARY_CHAR_OFFSET && wc < (BINARY_CHAR_OFFSET + 256)) {
173 + res = 1;
174 + tmpbuf[0] = (char) (wc - BINARY_CHAR_OFFSET);
175 + } else
176 +#endif
177 + res = wcrtomb(tmpbuf, wc, &mbs);
178 + if (res > 0) {
179 + if (fwrite(tmpbuf, res, 1, f) != 1)
180 + break;
183 +#endif /* UTF8 */
184 return i;
187 @@ -290,12 +352,46 @@
188 int i, file, blocklen;
189 long current = edit->curs1;
190 unsigned char *buf;
191 +#ifdef UTF8
192 + mbstate_t mbs;
193 + int bufstart = 0;
195 + memset (&mbs, 0, sizeof (mbs));
196 +#endif /* UTF8 */
197 if ((file = mc_open (filename, O_RDONLY | O_BINARY)) == -1)
198 return 0;
199 buf = g_malloc (TEMP_BUF_LEN);
200 +#ifndef UTF8
201 while ((blocklen = mc_read (file, (char *) buf, TEMP_BUF_LEN)) > 0) {
202 for (i = 0; i < blocklen; i++)
203 edit_insert (edit, buf[i]);
204 +#else /* UTF8 */
205 + while ((blocklen = mc_read (file, (char *) buf + bufstart, TEMP_BUF_LEN - bufstart)) > 0) {
206 + blocklen += bufstart;
207 + bufstart = 0;
208 + for (i = 0; i < blocklen; ) {
209 + mc_wchar_t wc;
210 + int j;
211 + int size = mbrtowc(&wc, (char *)buf + i, blocklen - i, &mbs);
212 + if (size == -2) { /*incomplete char*/
213 + bufstart = blocklen - i;
214 + memcpy(buf, buf+i, bufstart);
215 + i = blocklen;
216 + memset (&mbs, 0, sizeof (mbs));
218 + else if (size <= 0) {
219 +#ifdef __STDC_ISO_10646__
220 + edit_insert (edit, BINARY_CHAR_OFFSET + (mc_wchar_t)buf[i]);
221 +#endif
222 + memset (&mbs, 0, sizeof (mbs));
223 + i++; /* skip broken char */
225 + else {
226 + edit_insert (edit, wc);
227 + i+=size;
230 +#endif /* UTF8 */
232 edit_cursor_move (edit, current - edit->curs1);
233 g_free (buf);
234 @@ -385,7 +481,11 @@
235 static int
236 edit_load_file (WEdit *edit)
238 +#ifndef UTF8
239 int fast_load = 1;
240 +#else /* UTF8 */
241 + int fast_load = 0; /* can't be used with multibyte characters */
242 +#endif /* UTF8 */
244 /* Cannot do fast load if a filter is used */
245 if (edit_find_filter (edit->filename) >= 0)
246 @@ -451,6 +551,7 @@
247 edit->prev_col = column;
248 edit_move_to_prev_col (edit, edit_bol (edit, edit->curs1));
249 edit_move_display (edit, line - (edit->num_widget_lines / 2));
250 + edit->charpoint = 0;
253 /* Save cursor position in the file */
254 @@ -534,7 +635,7 @@
255 edit_set_filename (edit, filename);
256 edit->stack_size = START_STACK_SIZE;
257 edit->stack_size_mask = START_STACK_SIZE - 1;
258 - edit->undo_stack = g_malloc ((edit->stack_size + 10) * sizeof (long));
259 + edit->undo_stack = g_malloc ((edit->stack_size + 10) * sizeof (struct action));
260 if (edit_load_file (edit)) {
261 /* edit_load_file already gives an error message */
262 if (to_free)
263 @@ -689,14 +790,23 @@
265 unsigned long sp = edit->stack_pointer;
266 unsigned long spm1;
267 - long *t;
269 + struct action *t;
270 + mc_wchar_t ch = 0;
272 + if (c == CHAR_INSERT || c == CHAR_INSERT_AHEAD) {
273 + va_list ap;
274 + va_start (ap, c);
275 + ch = va_arg (ap, mc_wint_t);
276 + va_end (ap);
279 /* first enlarge the stack if necessary */
280 if (sp > edit->stack_size - 10) { /* say */
281 if (option_max_undo < 256)
282 option_max_undo = 256;
283 if (edit->stack_size < (unsigned long) option_max_undo) {
284 - t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (long));
285 + t = g_realloc (edit->undo_stack, (edit->stack_size * 2 + 10) * sizeof (struct action));
286 if (t) {
287 edit->undo_stack = t;
288 edit->stack_size <<= 1;
289 @@ -711,7 +821,7 @@
290 #ifdef FAST_MOVE_CURSOR
291 if (c == CURS_LEFT_LOTS || c == CURS_RIGHT_LOTS) {
292 va_list ap;
293 - edit->undo_stack[sp] = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT;
294 + edit->undo_stack[sp].flags = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT;
295 edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
296 va_start (ap, c);
297 c = -(va_arg (ap, int));
298 @@ -722,12 +832,14 @@
299 && spm1 != edit->stack_bottom
300 && ((sp - 2) & edit->stack_size_mask) != edit->stack_bottom) {
301 int d;
302 - if (edit->undo_stack[spm1] < 0) {
303 - d = edit->undo_stack[(sp - 2) & edit->stack_size_mask];
304 - if (d == c) {
305 - if (edit->undo_stack[spm1] > -1000000000) {
306 + mc_wchar_t d_ch;
307 + if (edit->undo_stack[spm1].flags < 0) {
308 + d = edit->undo_stack[(sp - 2) & edit->stack_size_mask].flags;
309 + d_ch = edit->undo_stack[(sp - 2) & edit->stack_size_mask].ch;
310 + if (d == c && d_ch == ch) {
311 + if (edit->undo_stack[spm1].flags > -1000000000) {
312 if (c < KEY_PRESS) /* --> no need to push multiple do-nothings */
313 - edit->undo_stack[spm1]--;
314 + edit->undo_stack[spm1].flags--;
315 return;
318 @@ -735,19 +847,20 @@
319 #ifndef NO_STACK_CURSMOVE_ANIHILATION
320 else if ((c == CURS_LEFT && d == CURS_RIGHT)
321 || (c == CURS_RIGHT && d == CURS_LEFT)) { /* a left then a right anihilate each other */
322 - if (edit->undo_stack[spm1] == -2)
323 + if (edit->undo_stack[spm1].flags == -2)
324 edit->stack_pointer = spm1;
325 else
326 - edit->undo_stack[spm1]++;
327 + edit->undo_stack[spm1].flags++;
328 return;
330 #endif
331 } else {
332 - d = edit->undo_stack[spm1];
333 - if (d == c) {
334 + d = edit->undo_stack[spm1].flags;
335 + d_ch = edit->undo_stack[spm1].ch;
336 + if (d == c && d_ch == ch) {
337 if (c >= KEY_PRESS)
338 return; /* --> no need to push multiple do-nothings */
339 - edit->undo_stack[sp] = -2;
340 + edit->undo_stack[sp].flags = -2;
341 goto check_bottom;
343 #ifndef NO_STACK_CURSMOVE_ANIHILATION
344 @@ -759,7 +872,9 @@
345 #endif
348 - edit->undo_stack[sp] = c;
349 + edit->undo_stack[sp].flags = c;
350 + edit->undo_stack[sp].ch = ch;
352 check_bottom:
354 edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
355 @@ -772,10 +887,10 @@
356 (((unsigned long) c + 1) & edit->stack_size_mask) == edit->stack_bottom)
357 do {
358 edit->stack_bottom = (edit->stack_bottom + 1) & edit->stack_size_mask;
359 - } while (edit->undo_stack[edit->stack_bottom] < KEY_PRESS && edit->stack_bottom != edit->stack_pointer);
360 + } while (edit->undo_stack[edit->stack_bottom].flags < KEY_PRESS && edit->stack_bottom != edit->stack_pointer);
362 /*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: */
363 - if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom] < KEY_PRESS)
364 + if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom].flags < KEY_PRESS)
365 edit->stack_bottom = edit->stack_pointer = 0;
368 @@ -784,30 +899,30 @@
369 then the file should be as it was when he loaded up. Then set edit->modified to 0.
371 static long
372 -pop_action (WEdit * edit)
373 +pop_action (WEdit * edit, struct action *c)
375 - long c;
376 unsigned long sp = edit->stack_pointer;
377 if (sp == edit->stack_bottom) {
378 - return STACK_BOTTOM;
379 + c->flags = STACK_BOTTOM;
380 + return c->flags;
382 sp = (sp - 1) & edit->stack_size_mask;
383 - if ((c = edit->undo_stack[sp]) >= 0) {
384 -/* edit->undo_stack[sp] = '@'; */
385 + *c = edit->undo_stack[sp];
386 + if (edit->undo_stack[sp].flags >= 0) {
387 edit->stack_pointer = (edit->stack_pointer - 1) & edit->stack_size_mask;
388 - return c;
389 + return c->flags;
391 if (sp == edit->stack_bottom) {
392 return STACK_BOTTOM;
394 - c = edit->undo_stack[(sp - 1) & edit->stack_size_mask];
395 - if (edit->undo_stack[sp] == -2) {
396 -/* edit->undo_stack[sp] = '@'; */
397 + *c = edit->undo_stack[(sp - 1) & edit->stack_size_mask];
399 + if (edit->undo_stack[sp].flags == -2) {
400 edit->stack_pointer = sp;
401 } else
402 - edit->undo_stack[sp]++;
403 + edit->undo_stack[sp].flags++;
405 - return c;
406 + return c->flags;
409 /* is called whenever a modification is made by one of the four routines below */
410 @@ -828,7 +943,7 @@
413 void
414 -edit_insert (WEdit *edit, int c)
415 +edit_insert (WEdit *edit, mc_wchar_t c)
417 /* check if file has grown to large */
418 if (edit->last_byte >= SIZE_LIMIT)
419 @@ -866,12 +981,11 @@
420 /* add a new buffer if we've reached the end of the last one */
421 if (!(edit->curs1 & M_EDIT_BUF_SIZE))
422 edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] =
423 - g_malloc (EDIT_BUF_SIZE);
424 + g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
426 /* perform the insertion */
427 - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->
428 - curs1 & M_EDIT_BUF_SIZE]
429 - = (unsigned char) c;
430 + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]
431 + [edit->curs1 & M_EDIT_BUF_SIZE] = c;
433 /* update file length */
434 edit->last_byte++;
435 @@ -882,7 +996,7 @@
438 /* same as edit_insert and move left */
439 -void edit_insert_ahead (WEdit * edit, int c)
440 +void edit_insert_ahead (WEdit * edit, mc_wchar_t c)
442 if (edit->last_byte >= SIZE_LIMIT)
443 return;
444 @@ -905,7 +1019,7 @@
445 edit->last_get_rule += (edit->last_get_rule >= edit->curs1);
447 if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
448 - edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE);
449 + edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
450 edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
452 edit->last_byte++;
453 @@ -915,7 +1029,7 @@
455 int edit_delete (WEdit * edit)
457 - int p;
458 + mc_wint_t p;
459 if (!edit->curs2)
460 return 0;
462 @@ -939,7 +1053,7 @@
463 edit->total_lines--;
464 edit->force |= REDRAW_AFTER_CURSOR;
466 - edit_push_action (edit, p + 256);
467 + edit_push_action (edit, CHAR_INSERT_AHEAD, p);
468 if (edit->curs1 < edit->start_display) {
469 edit->start_display--;
470 if (p == '\n')
471 @@ -953,7 +1067,7 @@
472 static int
473 edit_backspace (WEdit * edit)
475 - int p;
476 + mc_wint_t p;
477 if (!edit->curs1)
478 return 0;
480 @@ -977,7 +1091,7 @@
481 edit->total_lines--;
482 edit->force |= REDRAW_AFTER_CURSOR;
484 - edit_push_action (edit, p);
485 + edit_push_action (edit, CHAR_INSERT, p);
487 if (edit->curs1 < edit->start_display) {
488 edit->start_display--;
489 @@ -990,10 +1104,18 @@
491 #ifdef FAST_MOVE_CURSOR
493 -static void memqcpy (WEdit * edit, unsigned char *dest, unsigned char *src, int n)
494 +static void memqcpy (WEdit * edit, mc_wchar_t *dest, mc_wchar_t *src, int n)
496 unsigned long next;
497 +#ifndef UTF8
498 while ((next = (unsigned long) memccpy (dest, src, '\n', n))) {
499 +#else /* UTF8 */
500 + while (n) {
501 + next = 0;
502 + while (next < n && src[next]!='\n') next++;
503 + if (next < n) next++;
504 + wmemcpy (dest, src, next)
505 +#endif /* UTF8 */
506 edit->curs_line--;
507 next -= (unsigned long) dest;
508 n -= next;
509 @@ -1006,7 +1128,7 @@
510 edit_move_backward_lots (WEdit *edit, long increment)
512 int r, s, t;
513 - unsigned char *p;
514 + mc_wchar_t *p;
516 if (increment > edit->curs1)
517 increment = edit->curs1;
518 @@ -1046,7 +1168,7 @@
519 edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
520 else
521 edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] =
522 - g_malloc (EDIT_BUF_SIZE);
523 + g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
524 } else {
525 g_free (p);
527 @@ -1084,7 +1206,7 @@
528 edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
529 else
530 edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] =
531 - g_malloc (EDIT_BUF_SIZE);
532 + g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
533 } else {
534 g_free (p);
536 @@ -1116,7 +1238,7 @@
538 c = edit_get_byte (edit, edit->curs1 - 1);
539 if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
540 - edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE);
541 + edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
542 edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
543 edit->curs2++;
544 c = edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE][(edit->curs1 - 1) & M_EDIT_BUF_SIZE];
545 @@ -1141,7 +1263,7 @@
547 c = edit_get_byte (edit, edit->curs1);
548 if (!(edit->curs1 & M_EDIT_BUF_SIZE))
549 - edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE);
550 + edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = g_malloc (EDIT_BUF_SIZE * sizeof(mc_wchar_t));
551 edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = c;
552 edit->curs1++;
553 c = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1];
554 @@ -1248,7 +1370,7 @@
555 q = edit->last_byte + 2;
557 for (col = 0, p = current; p < q; p++) {
558 - int c;
559 + mc_wchar_t c;
560 if (cols != -10) {
561 if (col == cols)
562 return p;
563 @@ -1266,7 +1388,7 @@
564 } else if (c < 32 || c == 127)
565 col += 2; /* Caret notation for control characters */
566 else
567 - col++;
568 + col += wcwidth(c);
570 return col;
572 @@ -1399,12 +1521,16 @@
573 is_blank (WEdit *edit, long offset)
575 long s, f;
576 - int c;
577 + mc_wchar_t c;
578 s = edit_bol (edit, offset);
579 f = edit_eol (edit, offset) - 1;
580 while (s <= f) {
581 c = edit_get_byte (edit, s++);
582 +#ifndef UTF8
583 if (!isspace (c))
584 +#else
585 + if (!iswspace (c))
586 +#endif /* UTF8 */
587 return 0;
589 return 1;
590 @@ -1659,6 +1785,7 @@
591 return 2;
592 return 0x80000000UL;
594 +#ifndef UTF8
595 if (isupper (c))
596 c = 'A';
597 else if (islower (c))
598 @@ -1669,6 +1796,18 @@
599 c = '0';
600 else if (isspace (c))
601 c = ' ';
602 +#else
603 + if (iswupper (c))
604 + c = 'A';
605 + else if (iswlower (c))
606 + c = 'a';
607 + else if (iswalpha (c))
608 + c = 'a';
609 + else if (iswdigit (c))
610 + c = '0';
611 + else if (iswspace (c))
612 + c = ' ';
613 +#endif /* UTF8 */
614 q = strchr (option_chars_move_whole_word, c);
615 if (!q)
616 return 0xFFFFFFFFUL;
617 @@ -1693,10 +1832,18 @@
618 c2 = edit_get_byte (edit, edit->curs1);
619 if (!(my_type_of (c1) & my_type_of (c2)))
620 break;
621 +#ifndef UTF8
622 if (isspace (c1) && !isspace (c2))
623 +#else
624 + if (iswspace (c1) && !iswspace (c2))
625 +#endif /* UTF8 */
626 break;
627 if (s)
628 +#ifndef UTF8
629 if (!isspace (c1) && isspace (c2))
630 +#else
631 + if (!iswspace (c1) && iswspace (c2))
632 +#endif /* UTF8 */
633 break;
636 @@ -1719,10 +1866,18 @@
637 c2 = edit_get_byte (edit, edit->curs1);
638 if (!(my_type_of (c1) & my_type_of (c2)))
639 break;
640 +#ifndef UTF8
641 if (isspace (c1) && !isspace (c2))
642 +#else
643 + if (iswspace (c1) && !iswspace (c2))
644 +#endif /* UTF8 */
645 break;
646 if (s)
647 +#ifndef UTF8
648 if (!isspace (c1) && isspace (c2))
649 +#else
650 + if (!iswspace (c1) && iswspace (c2))
651 +#endif /* UTF8 */
652 break;
655 @@ -1742,7 +1897,11 @@
656 break;
657 c1 = edit_delete (edit);
658 c2 = edit_get_byte (edit, edit->curs1);
659 +#ifndef UTF8
660 if ((isspace (c1) == 0) != (isspace (c2) == 0))
661 +#else
662 + if ((iswspace (c1) == 0) != (iswspace (c2) == 0))
663 +#endif /* UTF8 */
664 break;
665 if (!(my_type_of (c1) & my_type_of (c2)))
666 break;
667 @@ -1757,7 +1916,11 @@
668 break;
669 c1 = edit_backspace (edit);
670 c2 = edit_get_byte (edit, edit->curs1 - 1);
671 +#ifndef UTF8
672 if ((isspace (c1) == 0) != (isspace (c2) == 0))
673 +#else
674 + if ((iswspace (c1) == 0) != (iswspace (c2) == 0))
675 +#endif /* UTF8 */
676 break;
677 if (!(my_type_of (c1) & my_type_of (c2)))
678 break;
679 @@ -1771,13 +1934,13 @@
680 static void
681 edit_do_undo (WEdit * edit)
683 - long ac;
684 + struct action ac;
685 long count = 0;
687 edit->stack_disable = 1; /* don't record undo's onto undo stack! */
689 - while ((ac = pop_action (edit)) < KEY_PRESS) {
690 - switch ((int) ac) {
691 + while (pop_action (edit, &ac) < KEY_PRESS) {
692 + switch ((int) ac.flags) {
693 case STACK_BOTTOM:
694 goto done_undo;
695 case CURS_RIGHT:
696 @@ -1798,31 +1961,33 @@
697 case COLUMN_OFF:
698 column_highlighting = 0;
699 break;
700 + case CHAR_INSERT:
701 + edit_insert (edit, ac.ch);
702 + break;
703 + case CHAR_INSERT_AHEAD:
704 + edit_insert_ahead (edit, ac.ch);
705 + break;
707 - if (ac >= 256 && ac < 512)
708 - edit_insert_ahead (edit, ac - 256);
709 - if (ac >= 0 && ac < 256)
710 - edit_insert (edit, ac);
712 - if (ac >= MARK_1 - 2 && ac < MARK_2 - 2) {
713 - edit->mark1 = ac - MARK_1;
714 + if (ac.flags >= MARK_1 - 2 && ac.flags < MARK_2 - 2) {
715 + edit->mark1 = ac.flags - MARK_1;
716 edit->column1 = edit_move_forward3 (edit, edit_bol (edit, edit->mark1), 0, edit->mark1);
717 - } else if (ac >= MARK_2 - 2 && ac < KEY_PRESS) {
718 - edit->mark2 = ac - MARK_2;
719 + } else if (ac.flags >= MARK_2 - 2 && ac.flags < KEY_PRESS) {
720 + edit->mark2 = ac.flags - MARK_2;
721 edit->column2 = edit_move_forward3 (edit, edit_bol (edit, edit->mark2), 0, edit->mark2);
723 if (count++)
724 edit->force |= REDRAW_PAGE; /* more than one pop usually means something big */
727 - if (edit->start_display > ac - KEY_PRESS) {
728 - edit->start_line -= edit_count_lines (edit, ac - KEY_PRESS, edit->start_display);
729 + if (edit->start_display > ac.flags - KEY_PRESS) {
730 + edit->start_line -= edit_count_lines (edit, ac.flags - KEY_PRESS, edit->start_display);
731 edit->force |= REDRAW_PAGE;
732 - } else if (edit->start_display < ac - KEY_PRESS) {
733 - edit->start_line += edit_count_lines (edit, edit->start_display, ac - KEY_PRESS);
734 + } else if (edit->start_display < ac.flags - KEY_PRESS) {
735 + edit->start_line += edit_count_lines (edit, edit->start_display, ac.flags - KEY_PRESS);
736 edit->force |= REDRAW_PAGE;
738 - edit->start_display = ac - KEY_PRESS; /* see push and pop above */
739 + edit->start_display = ac.flags - KEY_PRESS; /* see push and pop above */
740 edit_update_curs_row (edit);
742 done_undo:;
743 @@ -2102,7 +2267,7 @@
744 * passed as -1. Commands are executed, and char_for_insertion is
745 * inserted at the cursor.
747 -void edit_execute_key_command (WEdit *edit, int command, int char_for_insertion)
748 +void edit_execute_key_command (WEdit *edit, int command, mc_wint_t char_for_insertion)
750 if (command == CK_Begin_Record_Macro) {
751 edit->macro_i = 0;
752 @@ -2137,7 +2302,7 @@
753 all of them. It also does not check for the Undo command.
755 void
756 -edit_execute_cmd (WEdit *edit, int command, int char_for_insertion)
757 +edit_execute_cmd (WEdit *edit, int command, mc_wint_t char_for_insertion)
759 edit->force |= REDRAW_LINE;
761 @@ -2170,7 +2335,7 @@
764 /* An ordinary key press */
765 - if (char_for_insertion >= 0) {
766 + if (char_for_insertion != (mc_wint_t) -1) {
767 if (edit->overwrite) {
768 if (edit_get_byte (edit, edit->curs1) != '\n')
769 edit_delete (edit);
770 --- mc-4.6.2-pre1/edit/edit.h
771 +++ mc-4.6.2-pre1/edit/edit.h
772 @@ -25,6 +25,27 @@
774 #include <stdio.h>
776 +#include "src/tty.h"
778 +#ifdef UTF8
779 +#include <wchar.h>
780 +#include <wctype.h>
782 +#define mc_wchar_t wchar_t
783 +#define mc_wint_t wint_t
785 +#else
787 +#define mc_wchar_t unsigned char
788 +#define mc_wint_t int
790 +#endif
793 +/* unicode private use area */
794 +#define BINARY_CHAR_OFFSET 0xFFE00
797 #define N_menus 5
799 #define SEARCH_DIALOG_OPTION_NO_SCANF (1 << 0)
800 @@ -86,6 +107,8 @@
801 #define START_STACK_SIZE 32
803 /* Some codes that may be pushed onto or returned from the undo stack */
804 +#define CHAR_INSERT 65
805 +#define CHAR_INSERT_AHEAD 66
806 #define CURS_LEFT 601
807 #define CURS_RIGHT 602
808 #define DELCHAR 603
809 @@ -105,7 +128,7 @@
811 struct macro {
812 short command;
813 - short ch;
814 + mc_wchar_t ch;
817 struct WEdit;
818 @@ -120,8 +143,12 @@
819 void menu_save_mode_cmd (void);
820 int edit_raw_key_query (const char *heading, const char *query, int cancel);
821 int edit_file (const char *_file, int line);
822 -int edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch);
823 +int edit_translate_key (WEdit *edit, long x_key, int *cmd, mc_wint_t *ch);
824 +#ifndef UTF8
825 int edit_get_byte (WEdit * edit, long byte_index);
826 +#else /* UTF8 */
827 +mc_wchar_t edit_get_byte (WEdit * edit, long byte_index);
828 +#endif /* UTF8 */
829 int edit_count_lines (WEdit * edit, long current, int upto);
830 long edit_move_forward (WEdit * edit, long current, int lines, long upto);
831 long edit_move_forward3 (WEdit * edit, long current, int cols, long upto);
832 @@ -148,11 +175,11 @@
833 void edit_delete_line (WEdit * edit);
835 int edit_delete (WEdit * edit);
836 -void edit_insert (WEdit * edit, int c);
837 +void edit_insert (WEdit * edit, mc_wchar_t c);
838 int edit_cursor_move (WEdit * edit, long increment);
839 void edit_push_action (WEdit * edit, long c, ...);
840 void edit_push_key_press (WEdit * edit);
841 -void edit_insert_ahead (WEdit * edit, int c);
842 +void edit_insert_ahead (WEdit * edit, mc_wchar_t c);
843 long edit_write_stream (WEdit * edit, FILE * f);
844 char *edit_get_write_filter (const char *writename, const char *filename);
845 int edit_save_confirm_cmd (WEdit * edit);
846 @@ -183,7 +210,7 @@
847 int eval_marks (WEdit * edit, long *start_mark, long *end_mark);
848 void edit_status (WEdit * edit);
849 void edit_execute_key_command (WEdit *edit, int command,
850 - int char_for_insertion);
851 + mc_wint_t char_for_insertion);
852 void edit_update_screen (WEdit * edit);
853 int edit_print_string (WEdit * e, const char *s);
854 void edit_move_to_line (WEdit * e, long line);
855 @@ -233,7 +260,7 @@
856 void format_paragraph (WEdit *edit, int force);
858 /* either command or char_for_insertion must be passed as -1 */
859 -void edit_execute_cmd (WEdit *edit, int command, int char_for_insertion);
860 +void edit_execute_cmd (WEdit *edit, int command, mc_wint_t char_for_insertion);
862 #define get_sys_error(s) (s)
864 --- mc-4.6.2-pre1/edit/editcmd.c
865 +++ mc-4.6.2-pre1/edit/editcmd.c
866 @@ -61,7 +61,7 @@
867 #define edit_get_save_file(f,h) input_expand_dialog (h, _(" Enter file name: "), f)
869 struct selection {
870 - unsigned char * text;
871 + mc_wchar_t *text;
872 int len;
875 @@ -84,12 +84,16 @@
876 #define MAX_REPL_LEN 1024
878 static int edit_save_cmd (WEdit *edit);
879 -static unsigned char *edit_get_block (WEdit *edit, long start,
880 +static mc_wchar_t *edit_get_block (WEdit *edit, long start,
881 long finish, int *l);
883 -static inline int my_lower_case (int c)
884 +static inline mc_wchar_t my_lower_case (mc_wchar_t c)
886 +#ifndef UTF8
887 return tolower(c & 0xFF);
888 +#else
889 + return towlower(c);
890 +#endif
893 static const char *
894 @@ -124,11 +128,11 @@
895 #endif /* !HAVE_MEMMOVE */
897 /* #define itoa MY_itoa <---- this line is now in edit.h */
898 -static char *
899 +static mc_wchar_t *
900 MY_itoa (int i)
902 - static char t[14];
903 - char *s = t + 13;
904 + static mc_wchar_t t[14];
905 + mc_wchar_t *s = t + 13;
906 int j = i;
907 *s-- = 0;
908 do {
909 @@ -213,6 +217,48 @@
910 doupdate();
913 +#ifdef UTF8
915 +static size_t
916 +wchar_write(int fd, mc_wchar_t *buf, size_t len)
918 + char *tmpbuf = g_malloc(len + MB_LEN_MAX);
919 + mbstate_t mbs;
920 + size_t i;
921 + size_t outlen = 0;
922 + size_t res;
924 + for (i = 0; i < len; i++) {
925 + if (outlen >= len) {
926 + if ((res = mc_write(fd, tmpbuf, outlen)) != outlen) {
927 + g_free(tmpbuf);
928 + return -1;
930 + outlen = 0;
932 + memset (&mbs, 0, sizeof (mbs));
933 +#ifdef __STDC_ISO_10646__
934 + if (buf[i] >= BINARY_CHAR_OFFSET && buf[i] < (BINARY_CHAR_OFFSET + 256)) {
935 + res = 1;
936 + tmpbuf[outlen] = (char) (buf[i] - BINARY_CHAR_OFFSET);
938 + } else
939 +#endif
940 + res = wcrtomb(tmpbuf + outlen, buf[i], &mbs);
941 + if (res > 0) {
942 + outlen += res;
945 + if ((res = mc_write(fd, tmpbuf, outlen)) != outlen) {
946 + g_free(tmpbuf);
947 + return -1;
949 + g_free(tmpbuf);
950 + return len;
953 +#endif /* UTF8 */
955 /* If 0 (quick save) then a) create/truncate <filename> file,
956 b) save to <filename>;
957 if 1 (safe save) then a) save to <tempnam>,
958 @@ -360,32 +406,48 @@
959 buf = 0;
960 filelen = edit->last_byte;
961 while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1) {
962 +#ifndef UTF8
963 if (mc_write (fd, (char *) edit->buffers1[buf], EDIT_BUF_SIZE)
964 +#else /* UTF8 */
965 + if (wchar_write (fd, edit->buffers1[buf], EDIT_BUF_SIZE)
966 +#endif /* UTF8 */
967 != EDIT_BUF_SIZE) {
968 mc_close (fd);
969 goto error_save;
971 buf++;
973 +#ifndef UTF8
974 if (mc_write
975 (fd, (char *) edit->buffers1[buf],
976 +#else /* UTF8 */
977 + if (wchar_write
978 + (fd, edit->buffers1[buf],
979 +#endif /* UTF8 */
980 edit->curs1 & M_EDIT_BUF_SIZE) !=
981 (edit->curs1 & M_EDIT_BUF_SIZE)) {
982 filelen = -1;
983 } else if (edit->curs2) {
984 edit->curs2--;
985 buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
986 - if (mc_write
987 - (fd,
988 - (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
989 +#ifndef UTF8
990 + if (mc_write(fd, (char *) edit->buffers2[buf] + EDIT_BUF_SIZE -
991 +#else /* UTF8 */
992 + if (wchar_write(fd, edit->buffers2[buf] + EDIT_BUF_SIZE -
993 +#endif /* UTF8 */
994 (edit->curs2 & M_EDIT_BUF_SIZE) - 1,
995 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) !=
996 1 + (edit->curs2 & M_EDIT_BUF_SIZE)) {
997 filelen = -1;
998 } else {
999 while (--buf >= 0) {
1000 +#ifndef UTF8
1001 if (mc_write
1002 (fd, (char *) edit->buffers2[buf],
1003 +#else /* UTF8 */
1004 + if (wchar_write
1005 + (fd, edit->buffers2[buf],
1006 +#endif /* UTF8 */
1007 EDIT_BUF_SIZE) != EDIT_BUF_SIZE) {
1008 filelen = -1;
1009 break;
1010 @@ -705,13 +767,21 @@
1011 if (!n || n == EOF)
1012 break;
1013 n = 0;
1014 +#ifndef UTF8
1015 while (fscanf (f, "%hd %hd, ", &macro[n].command, &macro[n].ch))
1016 +#else /* UTF8 */
1017 + while (fscanf (f, "%hd %lu, ", &macro[n].command, &macro[n].ch))
1018 +#endif /* UTF8 */
1019 n++;
1020 fscanf (f, ";\n");
1021 if (s != k) {
1022 fprintf (g, ("key '%d 0': "), s);
1023 for (i = 0; i < n; i++)
1024 +#ifndef UTF8
1025 fprintf (g, "%hd %hd, ", macro[i].command, macro[i].ch);
1026 +#else /* UTF8 */
1027 + fprintf (g, "%hd %lu, ", macro[i].command, macro[i].ch);
1028 +#endif /* UTF8 */
1029 fprintf (g, ";\n");
1032 @@ -744,7 +814,11 @@
1033 if (f) {
1034 fprintf (f, ("key '%d 0': "), s);
1035 for (i = 0; i < n; i++)
1036 +#ifndef UTF8
1037 fprintf (f, "%hd %hd, ", macro[i].command, macro[i].ch);
1038 +#else /* UTF8 */
1039 + fprintf (f, "%hd %lu, ", macro[i].command, macro[i].ch);
1040 +#endif /* UTF8 */
1041 fprintf (f, ";\n");
1042 fclose (f);
1043 if (saved_macros_loaded) {
1044 @@ -794,10 +868,18 @@
1045 saved_macro[i++] = s;
1046 if (!found) {
1047 *n = 0;
1048 +#ifndef UTF8
1049 while (*n < MAX_MACRO_LENGTH && 2 == fscanf (f, "%hd %hd, ", &macro[*n].command, &macro[*n].ch))
1050 +#else /* UTF8 */
1051 + while (*n < MAX_MACRO_LENGTH && 2 == fscanf (f, "%hd %lu, ", &macro[*n].command, &macro[*n].ch))
1052 +#endif /* UTF8 */
1053 (*n)++;
1054 } else {
1055 +#ifndef UTF8
1056 while (2 == fscanf (f, "%hd %hd, ", &dummy.command, &dummy.ch));
1057 +#else /* UTF8 */
1058 + while (2 == fscanf (f, "%hd %lu, ", &dummy.command, &dummy.ch));
1059 +#endif /* UTF8 */
1061 fscanf (f, ";\n");
1062 if (s == k)
1063 @@ -944,7 +1026,7 @@
1064 #define space_width 1
1066 static void
1067 -edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
1068 +edit_insert_column_of_text (WEdit * edit, mc_wchar_t *data, int size, int width)
1070 long cursor;
1071 int i, col;
1072 @@ -992,7 +1074,7 @@
1074 long start_mark, end_mark, current = edit->curs1;
1075 int size;
1076 - unsigned char *copy_buf;
1077 + mc_wchar_t *copy_buf;
1079 edit_update_curs_col (edit);
1080 if (eval_marks (edit, &start_mark, &end_mark))
1081 @@ -1032,7 +1114,7 @@
1083 long count;
1084 long current;
1085 - unsigned char *copy_buf;
1086 + mc_wchar_t *copy_buf;
1087 long start_mark, end_mark;
1088 int deleted = 0;
1089 int x = 0;
1090 @@ -1093,7 +1175,7 @@
1091 edit_push_action (edit, COLUMN_ON);
1092 column_highlighting = 0;
1093 } else {
1094 - copy_buf = g_malloc (end_mark - start_mark);
1095 + copy_buf = g_malloc ((end_mark - start_mark) * sizeof(mc_wchar_t));
1096 edit_cursor_move (edit, start_mark - edit->curs1);
1097 edit_scroll_screen_over_cursor (edit);
1098 count = start_mark;
1099 @@ -1432,7 +1514,11 @@
1100 /* This function is a modification of mc-3.2.10/src/view.c:regexp_view_search() */
1101 /* returns -3 on error in pattern, -1 on not found, found_len = 0 if either */
1102 static int
1103 +#ifndef UTF8
1104 string_regexp_search (char *pattern, char *string, int match_type,
1105 +#else /* UTF8 */
1106 +string_regexp_search (char *pattern, mc_wchar_t *wstring, int match_type,
1107 +#endif /* UTF8 */
1108 int match_bol, int icase, int *found_len, void *d)
1110 static regex_t r;
1111 @@ -1441,6 +1527,11 @@
1112 regmatch_t *pmatch;
1113 static regmatch_t s[1];
1115 +#ifdef UTF8
1116 + char *string;
1117 + int i;
1118 +#endif /* UTF8 */
1120 pmatch = (regmatch_t *) d;
1121 if (!pmatch)
1122 pmatch = s;
1123 @@ -1460,13 +1551,51 @@
1124 old_type = match_type;
1125 old_icase = icase;
1128 +#ifdef UTF8
1129 + string = wchar_to_mbstr(wstring);
1130 + if (string == NULL)
1131 + return -1;
1132 +#endif /* UTF8 */
1134 if (regexec
1135 (&r, string, d ? NUM_REPL_ARGS : 1, pmatch,
1136 ((match_bol
1137 || match_type != match_normal) ? 0 : REG_NOTBOL)) != 0) {
1138 *found_len = 0;
1140 +#ifdef UTF8
1141 + g_free(string);
1142 +#endif /* UTF8 */
1144 return -1;
1147 +#ifdef UTF8
1148 + for (i = 0; i < (d ? NUM_REPL_ARGS : 1); i++) {
1149 + char tmp;
1150 + int new_o;
1152 + if (pmatch[i].rm_so < 0)
1153 + continue;
1154 + tmp = string[pmatch[i].rm_so];
1155 + string[pmatch[i].rm_so] = 0;
1156 + new_o = mbstrlen(string);
1157 + string[pmatch[i].rm_so] = tmp;
1158 + pmatch[i].rm_so = new_o;
1160 + if (pmatch[i].rm_eo < 0)
1161 + continue;
1162 + tmp = string[pmatch[i].rm_eo];
1163 + string[pmatch[i].rm_eo] = 0;
1164 + new_o = mbstrlen(string);
1165 + string[pmatch[i].rm_eo] = tmp;
1166 + pmatch[i].rm_eo = new_o;
1169 + g_free(string);
1170 +#endif /* UTF8 */
1172 *found_len = pmatch[0].rm_eo - pmatch[0].rm_so;
1173 return (pmatch[0].rm_so);
1175 @@ -1474,13 +1603,29 @@
1176 /* thanks to Liviu Daia <daia@stoilow.imar.ro> for getting this
1177 (and the above) routines to work properly - paul */
1179 +#ifndef UTF8
1180 typedef int (*edit_getbyte_fn) (WEdit *, long);
1181 +#else /* UTF8 */
1182 +typedef mc_wchar_t (*edit_getbyte_fn) (WEdit *, long);
1183 +#endif /* UTF8 */
1185 static long
1186 +#ifndef UTF8
1187 edit_find_string (long start, unsigned char *exp, int *len, long last_byte, edit_getbyte_fn get_byte, void *data, int once_only, void *d)
1188 +#else /* UTF8 */
1189 +edit_find_string (long start, unsigned char *exp_mb, int *len, long last_byte, edit_getbyte_fn get_byte, void *data, int once_only, void *d)
1190 +#endif /* UTF8 */
1192 long p, q = 0;
1193 - long l = strlen ((char *) exp), f = 0;
1194 + long f = 0;
1196 +#ifndef UTF8
1197 + long l = strlen ((char *) exp);
1198 +#else /* UTF8 */
1199 + mc_wchar_t *exp = mbstr_to_wchar((char *)exp_mb);
1200 + mc_wchar_t *exp_backup = exp;
1201 + long l = wcslen(exp);
1202 +#endif /* UTF8 */
1203 int n = 0;
1205 for (p = 0; p < l; p++) /* count conversions... */
1206 @@ -1489,19 +1634,22 @@
1207 n++;
1209 if (replace_scanf || replace_regexp) {
1210 - int c;
1211 - unsigned char *buf;
1212 - unsigned char mbuf[MAX_REPL_LEN * 2 + 3];
1213 + mc_wint_t c;
1214 + mc_wchar_t *buf;
1215 + mc_wchar_t mbuf[MAX_REPL_LEN * 2 + 3];
1217 replace_scanf = (!replace_regexp); /* can't have both */
1219 buf = mbuf;
1221 if (replace_scanf) {
1222 - unsigned char e[MAX_REPL_LEN];
1223 - if (n >= NUM_REPL_ARGS)
1224 - return -3;
1226 + mc_wchar_t e[MAX_REPL_LEN];
1227 + if (n >= NUM_REPL_ARGS) {
1228 +#ifdef UTF8
1229 + g_free(exp_backup);
1230 +#endif /* UTF8 */
1231 + return -3;
1233 if (replace_case) {
1234 for (p = start; p < last_byte && p < start + MAX_REPL_LEN; p++)
1235 buf[p - start] = (*get_byte) (data, p);
1236 @@ -1515,20 +1663,36 @@
1239 buf[(q = p - start)] = 0;
1240 +#ifndef UTF8
1241 strcpy ((char *) e, (char *) exp);
1242 strcat ((char *) e, "%n");
1243 +#else /* UTF8 */
1244 + wcscpy (e, exp);
1245 + wcscat (e, L"%n");
1246 +#endif /* UTF8 */
1247 exp = e;
1249 while (q) {
1250 *((int *) sargs[n]) = 0; /* --> here was the problem - now fixed: good */
1251 +#ifndef UTF8
1252 if (n == sscanf ((char *) buf, (char *) exp, SCANF_ARGS)) {
1253 +#else /* UTF8 */
1254 + if (n == swscanf (buf, exp, SCANF_ARGS)) {
1255 +#endif /* UTF8 */
1256 if (*((int *) sargs[n])) {
1257 *len = *((int *) sargs[n]);
1258 +#ifdef UTF8
1259 + g_free(exp_backup);
1260 +#endif /* UTF8 */
1261 return start;
1264 - if (once_only)
1265 + if (once_only) {
1266 +#ifdef UTF8
1267 + g_free(exp_backup);
1268 +#endif /* UTF8 */
1269 return -2;
1271 if (q + start < last_byte) {
1272 if (replace_case) {
1273 buf[q] = (*get_byte) (data, q + start);
1274 @@ -1542,7 +1706,11 @@
1275 start++;
1276 buf++; /* move the window along */
1277 if (buf == mbuf + MAX_REPL_LEN) { /* the window is about to go past the end of array, so... */
1278 +#ifndef UTF8
1279 memmove (mbuf, buf, strlen ((char *) buf) + 1); /* reset it */
1280 +#else /* UTF8 */
1281 + wmemmove (mbuf, buf, (wcslen (buf) + 1)); /* reset it */
1282 +#endif /* UTF8 */
1283 buf = mbuf;
1285 q--;
1286 @@ -1569,10 +1737,16 @@
1288 buf = mbuf;
1289 while (q) {
1290 +#ifndef UTF8
1291 found_start = string_regexp_search ((char *) exp, (char *) buf, match_normal, match_bol, !replace_case, len, d);
1293 +#else /* UTF8 */
1294 + found_start = string_regexp_search ((char *) exp_mb, buf, match_normal, match_bol, !replace_case, len, d);
1295 +#endif /* UTF8 */
1296 if (found_start <= -2) { /* regcomp/regexec error */
1297 *len = 0;
1298 +#ifdef UTF8
1299 + g_free (exp_backup);
1300 +#endif /* UTF8 */
1301 return -3;
1303 else if (found_start == -1) /* not found: try next line */
1304 @@ -1583,15 +1757,27 @@
1305 match_bol = 0;
1306 continue;
1308 - else /* found */
1309 + else { /* found */
1310 +#ifdef UTF8
1311 + g_free(exp_backup);
1312 +#endif /* UTF8 */
1313 return (start + offset - q + found_start);
1316 - if (once_only)
1317 + if (once_only) {
1318 +#ifdef UTF8
1319 + g_free(exp_backup);
1320 +#endif /* UTF8 */
1321 return -2;
1324 if (buf[q - 1] != '\n') { /* incomplete line: try to recover */
1325 buf = mbuf + MAX_REPL_LEN / 2;
1326 +#ifndef UTF8
1327 q = strlen ((const char *) buf);
1328 +#else /* UTF8 */
1329 + q = wcslen (buf);
1330 +#endif /* UTF8 */
1331 memmove (mbuf, buf, q);
1332 p = start + q;
1333 move_win = 1;
1334 @@ -1601,36 +1787,59 @@
1337 } else {
1338 +#ifndef UTF8
1339 *len = strlen ((const char *) exp);
1340 +#else /* UTF8 */
1341 + *len = wcslen (exp);
1342 +#endif /* UTF8 */
1343 if (replace_case) {
1344 for (p = start; p <= last_byte - l; p++) {
1345 - if ((*get_byte) (data, p) == (unsigned char)exp[0]) { /* check if first char matches */
1346 + if ((*get_byte) (data, p) == exp[0]) { /* check if first char matches */
1347 for (f = 0, q = 0; q < l && f < 1; q++)
1348 - if ((*get_byte) (data, q + p) != (unsigned char)exp[q])
1349 + if ((*get_byte) (data, q + p) != exp[q])
1350 f = 1;
1351 - if (f == 0)
1352 + if (f == 0) {
1353 +#ifdef UTF8
1354 + g_free (exp_backup);
1355 +#endif /* UTF8 */
1356 return p;
1359 - if (once_only)
1360 + if (once_only) {
1361 +#ifdef UTF8
1362 + g_free(exp_backup);
1363 +#endif /* UTF8 */
1364 return -2;
1367 } else {
1368 for (p = 0; exp[p] != 0; p++)
1369 exp[p] = my_lower_case (exp[p]);
1371 for (p = start; p <= last_byte - l; p++) {
1372 - if (my_lower_case ((*get_byte) (data, p)) == (unsigned char)exp[0]) {
1373 + if (my_lower_case ((*get_byte) (data, p)) == exp[0]) {
1374 for (f = 0, q = 0; q < l && f < 1; q++)
1375 - if (my_lower_case ((*get_byte) (data, q + p)) != (unsigned char)exp[q])
1376 + if (my_lower_case ((*get_byte) (data, q + p)) != exp[q])
1377 f = 1;
1378 - if (f == 0)
1379 + if (f == 0) {
1380 +#ifdef UTF8
1381 + g_free (exp_backup);
1382 +#endif /* UTF8 */
1383 return p;
1386 - if (once_only)
1387 + if (once_only) {
1388 +#ifdef UTF8
1389 + g_free (exp_backup);
1390 +#endif /* UTF8 */
1391 return -2;
1396 +#ifdef UTF8
1397 + g_free (exp_backup);
1398 +#endif /* UTF8 */
1399 return -2;
1402 @@ -1644,9 +1853,14 @@
1404 while ((p = edit_find_string (p, exp, len, last_byte, get_byte, data, once_only, d)) >= 0) {
1405 if (replace_whole) {
1406 +#ifndef UTF8
1407 /*If the bordering chars are not in option_whole_chars_search then word is whole */
1408 if (!strcasechr (option_whole_chars_search, (*get_byte) (data, p - 1))
1409 && !strcasechr (option_whole_chars_search, (*get_byte) (data, p + *len)))
1410 +#else /* UTF8 */
1411 + if (!iswalnum((*get_byte) (data, p - 1))
1412 + && !iswalnum((*get_byte) (data, p + *len)))
1413 +#endif /* UTF8 */
1414 return p;
1415 if (once_only)
1416 return -2;
1417 @@ -1678,6 +1892,7 @@
1419 #define is_digit(x) ((x) >= '0' && (x) <= '9')
1421 +#ifndef UTF8
1422 #define snprint(v) { \
1423 *p1++ = *p++; \
1424 *p1 = '\0'; \
1425 @@ -1685,33 +1900,48 @@
1426 if (n >= (size_t) (e - s)) goto nospc; \
1427 s += n; \
1429 +#else /* UTF8 */
1430 +#define snprint(v) { \
1431 + *p1++ = *p++; \
1432 + *p1 = '\0'; \
1433 + n = swprintf(s, e-s, q1,v); \
1434 + if (n >= (size_t) (e - s)) goto nospc; \
1435 + s += n; \
1437 +#endif /* UTF8 */
1439 /* this function uses the sprintf command to do a vprintf */
1440 /* it takes pointers to arguments instead of the arguments themselves */
1441 /* The return value is the number of bytes written excluding '\0'
1442 if successfull, -1 if the resulting string would be too long and
1443 -2 if the format string is errorneous. */
1444 -static int snprintf_p (char *str, size_t size, const char *fmt,...)
1445 - __attribute__ ((format (printf, 3, 4)));
1447 -static int snprintf_p (char *str, size_t size, const char *fmt,...)
1448 +static int snprintf_p (mc_wchar_t *str, size_t size, const mc_wchar_t *fmt,...)
1450 va_list ap;
1451 size_t n;
1452 - const char *q, *p;
1453 - char *s = str, *e = str + size;
1454 - char q1[40];
1455 - char *p1;
1456 + const mc_wchar_t *q, *p;
1457 + mc_wchar_t *s = str, *e = str + size;
1458 + mc_wchar_t q1[40];
1460 + mc_wchar_t *p1;
1461 int nargs = 0;
1463 va_start (ap, fmt);
1464 p = q = fmt;
1466 +#ifndef UTF8
1467 while ((p = strchr (p, '%'))) {
1468 +#else /* UTF8 */
1469 + while ((p = wcschr (p, L'%'))) {
1470 +#endif /* UTF8 */
1471 n = p - q;
1472 if (n >= (size_t) (e - s))
1473 goto nospc;
1474 +#ifndef UTF8
1475 memcpy (s, q, n); /* copy stuff between format specifiers */
1476 +#else /* UTF8 */
1477 + wmemcpy (s, q, n); /* copy stuff between format specifiers */
1478 +#endif /* UTF8 */
1479 s += n;
1480 q = p;
1481 p1 = q1;
1482 @@ -1739,45 +1969,78 @@
1483 *p1++ = *p++;
1484 if (*p == '*') {
1485 p++;
1486 +#ifndef UTF8
1487 strcpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace field width with a number */
1488 p1 += strlen (p1);
1489 +#else /* UTF8 */
1490 + wcscpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace field width with a number */
1491 + p1 += wcslen (p1);
1492 +#endif /* UTF8 */
1493 } else {
1494 - while (is_digit (*p) && p1 < q1 + 20)
1495 +#ifndef UTF8
1496 + while (is_digit (*p)
1497 +#else /* UTF8 */
1498 + while (iswdigit (*p)
1499 +#endif /* UTF8 */
1500 + && p1 < q1 + 20)
1501 *p1++ = *p++;
1502 - if (is_digit (*p))
1503 +#ifndef UTF8
1504 + if (is_digit (*p))
1505 +#else /* UTF8 */
1506 + if (iswdigit (*p))
1507 +#endif /* UTF8 */
1508 goto err;
1510 if (*p == '.')
1511 *p1++ = *p++;
1512 if (*p == '*') {
1513 p++;
1514 +#ifndef UTF8
1515 strcpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace precision with a number */
1516 p1 += strlen (p1);
1517 +#else /* UTF8 */
1518 + wcscpy (p1, MY_itoa (*va_arg (ap, int *))); /* replace precision with a number */
1519 + p1 += wcslen (p1);
1520 +#endif /* UTF8 */
1521 } else {
1522 - while (is_digit (*p) && p1 < q1 + 32)
1523 +#ifndef UTF8
1524 + while (is_digit (*p)
1525 +#else /* UTF8 */
1526 + while (iswdigit (*p)
1527 +#endif /* UTF8 */
1528 + && p1 < q1 + 32)
1529 *p1++ = *p++;
1530 - if (is_digit (*p))
1531 +#ifndef UTF8
1532 + if (is_digit (*p))
1533 +#else /* UTF8 */
1534 + if (iswdigit (*p))
1535 +#endif /* UTF8 */
1536 goto err;
1538 /* flags done, now get argument */
1539 if (*p == 's') {
1540 +#ifndef UTF8
1541 snprint (va_arg (ap, char *));
1542 +#else /* UTF8 */
1543 + *p1++ = 'l';
1544 + snprint (va_arg (ap, mc_wchar_t *));
1545 +#endif /* UTF8 */
1546 } else if (*p == 'h') {
1547 - if (strchr ("diouxX", *p))
1548 + if (*p < 128 && strchr ("diouxX", *p))
1549 snprint (*va_arg (ap, short *));
1550 } else if (*p == 'l') {
1551 *p1++ = *p++;
1552 - if (strchr ("diouxX", *p))
1553 + if (*p < 128 && strchr ("diouxX", *p))
1554 snprint (*va_arg (ap, long *));
1555 - } else if (strchr ("cdiouxX", *p)) {
1556 + } else if (*p < 128 && strchr ("cdiouxX", *p)) {
1557 snprint (*va_arg (ap, int *));
1558 } else if (*p == 'L') {
1559 *p1++ = *p++;
1560 - if (strchr ("EefgG", *p))
1561 + if (*p < 128 && strchr ("EefgG", *p))
1562 snprint (*va_arg (ap, double *)); /* should be long double */
1563 - } else if (strchr ("EefgG", *p)) {
1564 + } else if (*p < 128 && strchr ("EefgG", *p)) {
1565 snprint (*va_arg (ap, double *));
1566 - } else if (strchr ("DOU", *p)) {
1567 + } else if (*p < 128 && strchr ("DOU", *p)) {
1568 snprint (*va_arg (ap, long *));
1569 } else if (*p == 'p') {
1570 snprint (*va_arg (ap, void **));
1571 @@ -1786,10 +2049,17 @@
1572 q = p;
1574 va_end (ap);
1575 +#ifndef UTF8
1576 n = strlen (q);
1577 if (n >= (size_t) (e - s))
1578 return -1;
1579 memcpy (s, q, n + 1);
1580 +#else /* UTF8 */
1581 + n = wcslen (q);
1582 + if (n >= (size_t) (e - s))
1583 + return -1;
1584 + wmemcpy (s, q, n + 1);
1585 +#endif /* UTF8 */
1586 return s + n - str;
1587 nospc:
1588 va_end (ap);
1589 @@ -1968,8 +2238,11 @@
1592 if (replace_yes) { /* delete then insert new */
1593 +#ifdef UTF8
1594 + mc_wchar_t *winput2 = mbstr_to_wchar(input2);
1595 +#endif /* UTF8 */
1596 if (replace_scanf) {
1597 - char repl_str[MAX_REPL_LEN + 2];
1598 + mc_wchar_t repl_str[MAX_REPL_LEN + 2];
1599 int ret = 0;
1601 /* we need to fill in sargs just like with scanf */
1602 @@ -1978,17 +2251,25 @@
1603 for (k = 1;
1604 k < NUM_REPL_ARGS && pmatch[k].rm_eo >= 0;
1605 k++) {
1606 +#ifndef UTF8
1607 unsigned char *t;
1608 +#else /* UTF8 */
1609 + mc_wchar_t *t;
1610 +#endif
1612 if (pmatch[k].rm_eo - pmatch[k].rm_so > 255) {
1613 ret = -1;
1614 break;
1616 +#ifndef UTF8
1617 t = (unsigned char *) &sargs[k - 1][0];
1618 +#else /* UTF8 */
1619 + t = (mc_wchar_t *) &sargs[k - 1][0];
1620 +#endif /* UTF8 */
1621 for (j = 0;
1622 j < pmatch[k].rm_eo - pmatch[k].rm_so
1623 && j < 255; j++, t++)
1624 - *t = (unsigned char) edit_get_byte (edit,
1625 + *t = edit_get_byte (edit,
1626 edit->
1627 search_start
1629 @@ -2006,14 +2287,23 @@
1631 if (!ret)
1632 ret =
1633 +#ifndef UTF8
1634 snprintf_p (repl_str, MAX_REPL_LEN + 2, input2,
1635 +#else /* UTF8 */
1636 + snprintf_p (repl_str, MAX_REPL_LEN + 2, winput2,
1637 +#endif /* UTF8 */
1638 PRINTF_ARGS);
1639 if (ret >= 0) {
1640 times_replaced++;
1641 while (i--)
1642 edit_delete (edit);
1643 +#ifndef UTF8
1644 while (repl_str[++i])
1645 edit_insert (edit, repl_str[i]);
1646 +#else /* UTF8 */
1647 + while (winput2[++i])
1648 + edit_insert (edit, winput2[i]);
1649 +#endif /* UTF8 */
1650 } else {
1651 edit_error_dialog (_(" Replace "),
1652 ret ==
1653 @@ -2027,10 +2317,18 @@
1654 times_replaced++;
1655 while (i--)
1656 edit_delete (edit);
1657 +#ifndef UTF8
1658 while (input2[++i])
1659 edit_insert (edit, input2[i]);
1660 +#else /* UTF8 */
1661 + while (winput2[++i])
1662 + edit_insert (edit, winput2[i]);
1663 +#endif /* UTF8 */
1665 edit->found_len = i;
1666 +#ifdef UTF8
1667 + g_free (winput2);
1668 +#endif /* UTF8 */
1670 /* so that we don't find the same string again */
1671 if (replace_backwards) {
1672 @@ -2203,16 +2501,17 @@
1673 #define TEMP_BUF_LEN 1024
1675 /* Return a null terminated length of text. Result must be g_free'd */
1676 -static unsigned char *
1677 +static mc_wchar_t *
1678 edit_get_block (WEdit *edit, long start, long finish, int *l)
1680 - unsigned char *s, *r;
1681 - r = s = g_malloc (finish - start + 1);
1682 + mc_wchar_t *s, *r;
1683 + r = s = g_malloc ((finish - start + 1) * sizeof(mc_wchar_t));
1684 if (column_highlighting) {
1685 *l = 0;
1686 /* copy from buffer, excluding chars that are out of the column 'margins' */
1687 while (start < finish) {
1688 - int c, x;
1689 + mc_wchar_t c;
1690 + int x;
1691 x = edit_move_forward3 (edit, edit_bol (edit, start), 0,
1692 start);
1693 c = edit_get_byte (edit, start);
1694 @@ -2245,11 +2544,15 @@
1695 return 0;
1697 if (column_highlighting) {
1698 - unsigned char *block, *p;
1699 + mc_wchar_t *block, *p;
1700 int r;
1701 p = block = edit_get_block (edit, start, finish, &len);
1702 while (len) {
1703 +#ifndef UTF8
1704 r = mc_write (file, p, len);
1705 +#else /* UTF8 */
1706 + r = wchar_write (file, p, len);
1707 +#endif /* UTF8 */
1708 if (r < 0)
1709 break;
1710 p += r;
1711 @@ -2257,15 +2560,19 @@
1713 g_free (block);
1714 } else {
1715 - unsigned char *buf;
1716 + mc_wchar_t *buf;
1717 int i = start, end;
1718 len = finish - start;
1719 - buf = g_malloc (TEMP_BUF_LEN);
1720 + buf = g_malloc (TEMP_BUF_LEN * sizeof(mc_wchar_t));
1721 while (start != finish) {
1722 end = min (finish, start + TEMP_BUF_LEN);
1723 for (; i < end; i++)
1724 buf[i - start] = edit_get_byte (edit, i);
1725 +#ifndef UTF8
1726 len -= mc_write (file, (char *) buf, end - start);
1727 +#else /* UTF8 */
1728 + len -= wchar_write (file, buf, end - start);
1729 +#endif /* UTF8 */
1730 start = end;
1732 g_free (buf);
1733 @@ -2603,17 +2910,20 @@
1735 /* prints at the cursor */
1736 /* returns the number of chars printed */
1737 +#ifndef UTF8
1738 int edit_print_string (WEdit * e, const char *s)
1739 +#else /* UTF8 */
1740 +int edit_print_wstring (WEdit * e, mc_wchar_t *s)
1741 +#endif /* UTF8 */
1743 int i = 0;
1744 while (s[i])
1745 - edit_execute_cmd (e, -1, (unsigned char) s[i++]);
1746 + edit_execute_cmd (e, -1, s[i++]);
1747 e->force |= REDRAW_COMPLETELY;
1748 edit_update_screen (e);
1749 return i;
1753 static void pipe_mail (WEdit *edit, char *to, char *subject, char *cc)
1755 FILE *p = 0;
1756 @@ -2707,15 +3017,20 @@
1757 /* find first character of current word */
1758 static int edit_find_word_start (WEdit *edit, long *word_start, int *word_len)
1760 - int i, c, last;
1761 + int i;
1762 + mc_wint_t c, last;
1764 /* return if at begin of file */
1765 if (edit->curs1 <= 0)
1766 return 0;
1768 - c = (unsigned char) edit_get_byte (edit, edit->curs1 - 1);
1769 + c = edit_get_byte (edit, edit->curs1 - 1);
1770 /* return if not at end or in word */
1771 +#ifndef UTF8
1772 if (isspace (c) || !(isalnum (c) || c == '_'))
1773 +#else /* UTF8 */
1774 + if (iswspace (c) || !(iswalnum (c) || c == '_'))
1775 +#endif /* UTF8 */
1776 return 0;
1778 /* search start of word to be completed */
1779 @@ -2725,11 +3040,19 @@
1780 return 0;
1782 last = c;
1783 - c = (unsigned char) edit_get_byte (edit, edit->curs1 - i);
1784 + c = edit_get_byte (edit, edit->curs1 - i);
1786 +#ifndef UTF8
1787 if (!(isalnum (c) || c == '_')) {
1788 +#else /* UTF8 */
1789 + if (!(iswalnum (c) || c == '_')) {
1790 +#endif /* UTF8 */
1791 /* return if word starts with digit */
1792 +#ifndef UTF8
1793 if (isdigit (last))
1794 +#else /* UTF8 */
1795 + if (iswdigit (last))
1796 +#endif /* UTF8 */
1797 return 0;
1799 *word_start = edit->curs1 - (i - 1); /* start found */
1800 @@ -2762,7 +3085,7 @@
1801 int *num)
1803 int len, max_len = 0, i, skip;
1804 - unsigned char *bufpos;
1805 + mc_wchar_t *bufpos;
1807 /* collect max MAX_WORD_COMPLETIONS completions */
1808 while (*num < MAX_WORD_COMPLETIONS) {
1809 @@ -2781,11 +3104,16 @@
1810 buffers1[start >> S_EDIT_BUF_SIZE][start & M_EDIT_BUF_SIZE];
1811 skip = 0;
1812 for (i = 0; i < *num; i++) {
1813 +#ifndef UTF8
1814 if (strncmp
1815 ((char *) &compl[i].text[word_len],
1816 - (char *) &bufpos[word_len], max (len,
1817 - compl[i].len) -
1818 - word_len) == 0) {
1819 + (char *) &bufpos[word_len],
1820 +#else /* UTF8 */
1821 + if (wcsncmp
1822 + ((wchar_t *) &compl[i].text[word_len],
1823 + (wchar_t *) &bufpos[word_len],
1824 +#endif /* UTF8 */
1825 + max (len, compl[i].len) - word_len) == 0) {
1826 skip = 1;
1827 break; /* skip it, already added */
1829 @@ -2793,7 +3121,7 @@
1830 if (skip)
1831 continue;
1833 - compl[*num].text = g_malloc (len + 1);
1834 + compl[*num].text = g_malloc ((len + 1) * sizeof(mc_wchar_t));
1835 compl[*num].len = len;
1836 for (i = 0; i < len; i++)
1837 compl[*num].text[i] = *(bufpos + i);
1838 @@ -2807,6 +3135,18 @@
1839 return max_len;
1842 +#ifdef UTF8
1843 +int edit_print_string (WEdit * e, const char *s)
1845 + int i;
1846 + mc_wchar_t *ws = mbstr_to_wchar(s);
1847 + i = edit_print_wstring (e, ws);
1848 + g_free(ws);
1849 + return i;
1852 +#endif /* UTF8 */
1855 /* let the user select its preferred completion */
1856 static void
1857 @@ -2819,6 +3159,9 @@
1858 WListbox *compl_list;
1859 int compl_dlg_h; /* completion dialog height */
1860 int compl_dlg_w; /* completion dialog width */
1861 +#ifdef UTF8
1862 + char *mbtext;
1863 +#endif /* UTF8 */
1865 /* calculate the dialog metrics */
1866 compl_dlg_h = num_compl + 2;
1867 @@ -2854,9 +3197,18 @@
1868 add_widget (compl_dlg, compl_list);
1870 /* fill the listbox with the completions */
1871 +#ifndef UTF8
1872 for (i = 0; i < num_compl; i++)
1873 listbox_add_item (compl_list, LISTBOX_APPEND_AT_END, 0,
1874 (char *) compl[i].text, NULL);
1875 +#else /* UTF8 */
1876 + for (i = 0; i < num_compl; i++) {
1877 + mbtext = wchar_to_mbstr(compl[i].text);
1878 + listbox_add_item (compl_list, LISTBOX_APPEND_AT_END, 0,
1879 + mbtext, NULL);
1880 + g_free(mbtext);
1882 +#endif /* UTF8 */
1884 /* pop up the dialog */
1885 run_dlg (compl_dlg);
1886 @@ -2864,9 +3216,17 @@
1887 /* apply the choosen completion */
1888 if (compl_dlg->ret_value == B_ENTER) {
1889 listbox_get_current (compl_list, &curr, NULL);
1890 - if (curr)
1891 + if (curr){
1892 +#ifndef UTF8
1893 for (curr += word_len; *curr; curr++)
1894 edit_insert (edit, *curr);
1895 +#else /* UTF8 */
1896 + mc_wchar_t *wc, *wccurr = mbstr_to_wchar(curr);
1897 + for (wc = wccurr + word_len; *wc; wc++)
1898 + edit_insert (edit, *wc);
1899 + g_free(wccurr);
1900 +#endif /* UTF8 */
1904 /* destroy dialog before return */
1905 @@ -2883,8 +3243,9 @@
1907 int word_len = 0, i, num_compl = 0, max_len;
1908 long word_start = 0;
1909 - unsigned char *bufpos;
1910 - char *match_expr;
1911 + mc_wchar_t *bufpos;
1912 + mc_wchar_t *match_expr;
1913 + char *mbmatch_expr;
1914 struct selection compl[MAX_WORD_COMPLETIONS]; /* completions */
1916 /* don't want to disturb another search */
1917 @@ -2901,16 +3262,32 @@
1918 /* prepare match expression */
1919 bufpos = &edit->buffers1[word_start >> S_EDIT_BUF_SIZE]
1920 [word_start & M_EDIT_BUF_SIZE];
1922 + match_expr = g_malloc((word_len + 14) * sizeof(mc_wchar_t));
1923 +#ifndef UTF8
1924 match_expr = g_strdup_printf ("%.*s[a-zA-Z_0-9]+", word_len, bufpos);
1925 +#else /* UTF8 */
1926 + wcsncpy (match_expr, bufpos, word_len);
1927 + match_expr[word_len] = '\0';
1928 + wcscat (match_expr, L"[a-zA-Z_0-9]+");
1929 +#endif /* UTF8 */
1931 /* init search: backward, regexp, whole word, case sensitive */
1932 edit_set_search_parameters (0, 1, 1, 1, 1);
1934 /* collect the possible completions */
1935 /* start search from curs1 down to begin of file */
1936 +#ifndef UTF8
1937 max_len =
1938 edit_collect_completions (edit, word_start, word_len, match_expr,
1939 (struct selection *) &compl, &num_compl);
1940 +#else /* UTF8 */
1941 + mbmatch_expr = wchar_to_mbstr(match_expr);
1942 + max_len =
1943 + edit_collect_completions (edit, word_start, word_len, mbmatch_expr,
1944 + (struct selection *) &compl, &num_compl);
1945 + g_free(mbmatch_expr);
1946 +#endif /* UTF8 */
1948 if (num_compl > 0) {
1949 /* insert completed word if there is only one match */
1950 --- mc-4.6.2-pre1/edit/editdraw.c
1951 +++ mc-4.6.2-pre1/edit/editdraw.c
1952 @@ -70,11 +70,16 @@
1953 * as decimal and as hex.
1955 if (edit->curs1 < edit->last_byte) {
1956 - unsigned char cur_byte = edit_get_byte (edit, edit->curs1);
1957 + mc_wchar_t cur_byte = edit_get_byte (edit, edit->curs1);
1958 +#ifndef UTF8
1959 g_snprintf (byte_str, sizeof (byte_str), "%c %3d 0x%02X",
1960 is_printable (cur_byte) ? cur_byte : '.',
1961 - (int) cur_byte,
1962 - (unsigned) cur_byte);
1963 +#else /* UTF8 */
1964 + g_snprintf (byte_str, sizeof(byte_str), "%lc %3d 0x%02X",
1965 + iswprint(cur_byte) ? cur_byte : '.',
1966 +#endif /* UTF8 */
1967 + (int) cur_byte,
1968 + (unsigned) cur_byte);
1969 } else {
1970 strcpy (byte_str, "<EOF>");
1972 @@ -206,11 +211,16 @@
1973 #define lowlevel_set_color(x) attrset(MY_COLOR_PAIR(color))
1974 #endif
1976 +struct line_s {
1977 + mc_wchar_t ch;
1978 + unsigned int style;
1981 static void
1982 print_to_widget (WEdit *edit, long row, int start_col, int start_col_real,
1983 - long end_col, unsigned int line[])
1984 + long end_col, struct line_s line[])
1986 - unsigned int *p;
1987 + struct line_s *p;
1989 int x = start_col_real + EDIT_TEXT_HORIZONTAL_OFFSET;
1990 int x1 = start_col + EDIT_TEXT_HORIZONTAL_OFFSET;
1991 @@ -224,9 +234,9 @@
1992 edit_move (x1 + FONT_OFFSET_X, y + FONT_OFFSET_Y);
1993 p = line;
1995 - while (*p) {
1996 + while (p->ch) {
1997 int style;
1998 - int textchar;
1999 + mc_wchar_t textchar;
2000 int color;
2002 if (cols_to_skip) {
2003 @@ -235,9 +245,9 @@
2004 continue;
2007 - style = *p & 0xFF00;
2008 - textchar = *p & 0xFF;
2009 - color = *p >> 16;
2010 + style = p->style & 0xFF00;
2011 + textchar = p->ch;
2012 + color = p->style >> 16;
2014 if (style & MOD_ABNORMAL) {
2015 /* Non-printable - use black background */
2016 @@ -266,8 +276,11 @@
2017 lowlevel_set_color (color);
2021 +#ifdef UTF8
2022 + SLsmg_write_nwchars(&textchar, 1);
2023 +#else
2024 addch (textchar);
2025 +#endif
2026 p++;
2029 @@ -279,11 +292,11 @@
2030 edit_draw_this_line (WEdit *edit, long b, long row, long start_col,
2031 long end_col)
2033 - static unsigned int line[MAX_LINE_LEN];
2034 - unsigned int *p = line;
2035 + struct line_s line[MAX_LINE_LEN];
2036 + struct line_s *p = line;
2037 long m1 = 0, m2 = 0, q, c1, c2, tws;
2038 int col, start_col_real;
2039 - unsigned int c;
2040 + mc_wint_t c;
2041 int color;
2042 int i;
2044 @@ -307,62 +320,89 @@
2047 while (col <= end_col - edit->start_col) {
2048 - *p = 0;
2049 + p->ch = 0;
2050 + p->style = 0;
2051 if (q == edit->curs1)
2052 - *p |= MOD_CURSOR;
2053 + p->style |= MOD_CURSOR;
2054 if (q >= m1 && q < m2) {
2055 if (column_highlighting) {
2056 int x;
2057 x = edit_move_forward3 (edit, b, 0, q);
2058 if (x >= c1 && x < c2)
2059 - *p |= MOD_MARKED;
2060 + p->style |= MOD_MARKED;
2061 } else
2062 - *p |= MOD_MARKED;
2063 + p->style |= MOD_MARKED;
2065 if (q == edit->bracket)
2066 - *p |= MOD_BOLD;
2067 + p->style |= MOD_BOLD;
2068 if (q >= edit->found_start
2069 && q < edit->found_start + edit->found_len)
2070 - *p |= MOD_BOLD;
2071 + p->style |= MOD_BOLD;
2072 c = edit_get_byte (edit, q);
2073 /* we don't use bg for mc - fg contains both */
2074 edit_get_syntax_color (edit, q, &color);
2075 - *p |= color << 16;
2076 + p->style |= color << 16;
2077 switch (c) {
2078 case '\n':
2079 col = end_col - edit->start_col + 1; /* quit */
2080 - *(p++) |= ' ';
2081 + p->ch = ' ';
2082 + p++;
2083 break;
2084 case '\t':
2085 i = TAB_SIZE - ((int) col % TAB_SIZE);
2086 col += i;
2087 if (use_colors && visible_tabs) {
2088 - c = (*p & ~MOD_CURSOR) | MOD_WHITESPACE;
2089 + c = (p->style & ~MOD_CURSOR) | MOD_WHITESPACE;
2090 if (i > 2) {
2091 - *(p++) |= '<' | MOD_WHITESPACE;
2092 - while (--i > 1)
2093 - *(p++) = c | '-';
2094 - *(p++) = c | '>';
2095 + p->ch = '<';
2096 + p->style |= MOD_WHITESPACE;
2097 + p++;
2098 + while (--i > 1) {
2099 + p->style = c;
2100 + p->ch = '-';
2101 + p++;
2103 + p->style = c;
2104 + p->ch = '>';
2105 + p++;
2106 } else if (i > 1) {
2107 - *(p++) |= '<' | MOD_WHITESPACE;
2108 - *(p++) = c | '>';
2109 - } else
2110 - *(p++) |= '>' | MOD_WHITESPACE;
2111 + p->style |= MOD_WHITESPACE;
2112 + p->ch = '<';
2113 + p++;
2114 + p->style = c;
2115 + p->ch = '>';
2116 + p++;
2117 + } else {
2118 + p->style |= MOD_WHITESPACE;
2119 + p->ch = '>';
2120 + p++;
2122 } else if (use_colors && visible_tws && q >= tws) {
2123 - *p |= '.' | MOD_WHITESPACE;
2124 - c = *(p++) & ~MOD_CURSOR;
2125 - while (--i)
2126 - *(p++) = c;
2127 + p->style |= MOD_WHITESPACE;
2128 + p->ch = '.';
2129 + p++;
2130 + c = p->style & ~MOD_CURSOR;
2131 + while (--i) {
2132 + p->style = c;
2133 + p->ch = ' ';
2134 + p++;
2136 } else {
2137 - *p |= ' ';
2138 - c = *(p++) & ~MOD_CURSOR;
2139 - while (--i)
2140 - *(p++) = c;
2141 + p->ch |= ' ';
2142 + c = p->style & ~MOD_CURSOR;
2143 + p++;
2144 + while (--i) {
2145 + p->style = c;
2146 + p->ch = ' ';
2147 + p++;
2150 break;
2151 case ' ':
2152 if (use_colors && visible_tws && q >= tws) {
2153 - *(p++) |= '.' | MOD_WHITESPACE;
2154 + p->ch = '.';
2155 + p->style |= MOD_WHITESPACE;
2156 + p++;
2157 col++;
2158 break;
2160 @@ -372,22 +412,47 @@
2162 /* Caret notation for control characters */
2163 if (c < 32) {
2164 - *(p++) = '^' | MOD_ABNORMAL;
2165 - *(p++) = (c + 0x40) | MOD_ABNORMAL;
2166 + p->ch = '^';
2167 + p->style = MOD_ABNORMAL;
2168 + p++;
2169 + p->ch = c + 0x40;
2170 + p->style = MOD_ABNORMAL;
2171 col += 2;
2172 break;
2174 if (c == 127) {
2175 - *(p++) = '^' | MOD_ABNORMAL;
2176 - *(p++) = '?' | MOD_ABNORMAL;
2177 + p->ch = '^';
2178 + p->style = MOD_ABNORMAL;
2179 + p++;
2180 + p->ch = '?';
2181 + p->style = MOD_ABNORMAL;
2182 + p++;
2183 col += 2;
2184 break;
2187 - if (is_printable (c)) {
2188 - *(p++) |= c;
2189 +#ifndef UTF8
2190 + if (is_printable (c)
2191 +#else /* UTF8 */
2192 + if (iswprint (c)
2193 +#ifdef __STDC_ISO_10646__
2194 + && (c < BINARY_CHAR_OFFSET || c >= (BINARY_CHAR_OFFSET + 256))
2195 +#endif
2196 +#endif /* UTF8 */
2197 + ) {
2198 + p->ch = c;
2199 + p++;
2201 +#ifdef UTF8
2202 + i = wcwidth(c);
2203 + if (i > 1) {
2204 + col += i - 1;
2206 +#endif /* UTF8 */
2207 } else {
2208 - *(p++) = '.' | MOD_ABNORMAL;
2209 + p->ch = '.';
2210 + p->style = MOD_ABNORMAL;
2211 + p++;
2213 col++;
2214 break;
2215 @@ -398,7 +463,7 @@
2216 } else {
2217 start_col_real = start_col = 0;
2219 - *p = 0;
2220 + p->ch = 0;
2222 print_to_widget (edit, row, start_col, start_col_real, end_col, line);
2224 --- mc-4.6.2-pre1/edit/editkeys.c
2225 +++ mc-4.6.2-pre1/edit/editkeys.c
2226 @@ -182,10 +182,10 @@
2227 * 'command' is one of the editor commands from editcmddef.h.
2230 -edit_translate_key (WEdit *edit, long x_key, int *cmd, int *ch)
2231 +edit_translate_key (WEdit *edit, long x_key, int *cmd, mc_wint_t *ch)
2233 int command = CK_Insert_Char;
2234 - int char_for_insertion = -1;
2235 + mc_wint_t char_for_insertion = -1;
2236 int i = 0;
2237 int extmod = 0;
2238 const edit_key_map_type *key_map = NULL;
2239 @@ -242,9 +242,30 @@
2240 /* an ordinary insertable character */
2241 if (x_key < 256 && !extmod) {
2242 int c = convert_from_input_c (x_key);
2244 +#ifdef UTF8
2245 + mbstate_t mbs;
2246 + int res;
2247 + mc_wchar_t wc;
2249 + memset (&mbs, 0, sizeof (mbs));
2251 + if (edit->charpoint >= MB_CUR_MAX) edit->charpoint = 0;
2253 + edit->charbuf[edit->charpoint++] = c;
2255 + res = mbrtowc(&wc, (char *)edit->charbuf, edit->charpoint, &mbs);
2256 + if (res < 0) {
2257 + if (res != -2) edit->charpoint = 0; /* broken multibyte char, skip */
2258 + return 0;
2260 + edit->charpoint = 0;
2262 + if (iswprint (wc)) {
2263 + char_for_insertion = wc;
2264 +#else
2265 if (is_printable (c)) {
2266 char_for_insertion = c;
2267 +#endif /* UTF8 */
2268 goto fin;
2271 @@ -283,7 +304,7 @@
2272 *cmd = command;
2273 *ch = char_for_insertion;
2275 - if (command == CK_Insert_Char && char_for_insertion == -1) {
2276 + if (command == CK_Insert_Char && char_for_insertion == (mc_wint_t)-1) {
2277 /* unchanged, key has no function here */
2278 return 0;
2280 --- mc-4.6.2-pre1/edit/editwidget.c
2281 +++ mc-4.6.2-pre1/edit/editwidget.c
2282 @@ -331,7 +331,8 @@
2284 case WIDGET_KEY:
2286 - int cmd, ch;
2287 + int cmd;
2288 + mc_wint_t ch;
2290 /* The user may override the access-keys for the menu bar. */
2291 if (edit_translate_key (e, parm, &cmd, &ch)) {
2292 --- mc-4.6.2-pre1/edit/wordproc.c
2293 +++ mc-4.6.2-pre1/edit/wordproc.c
2294 @@ -40,7 +40,12 @@
2296 #define tab_width option_tab_spacing
2298 +#ifndef UTF8
2299 #define NO_FORMAT_CHARS_START "-+*\\,.;:&>"
2300 +#else /* UTF8 */
2301 +#define NO_FORMAT_CHARS_START L"-+*\\,.;:&>"
2302 +#endif /* UTF8 */
2304 #define FONT_MEAN_WIDTH 1
2306 static long
2307 @@ -57,14 +62,21 @@
2308 p = edit_move_forward (edit, p, line - l, 0);
2310 p = edit_bol (edit, p);
2312 +#ifndef UTF8
2313 while (strchr ("\t ", edit_get_byte (edit, p)))
2314 +#else /* UTF8 */
2315 + while (wcschr (L"\t ", edit_get_byte (edit, p)))
2316 +#endif /* UTF8 */
2318 p++;
2319 return p;
2322 static int bad_line_start (WEdit * edit, long p)
2324 - int c;
2325 + mc_wint_t c;
2327 c = edit_get_byte (edit, p);
2328 if (c == '.') { /* `...' is acceptable */
2329 if (edit_get_byte (edit, p + 1) == '.')
2330 @@ -78,7 +90,13 @@
2331 return 0; /* `---' is acceptable */
2332 return 1;
2335 +#ifndef UTF8
2336 if (strchr (NO_FORMAT_CHARS_START, c))
2337 +#else /* UTF8 */
2338 + if (wcschr (NO_FORMAT_CHARS_START, c))
2339 +#endif /* UTF8 */
2341 return 1;
2342 return 0;
2344 @@ -131,33 +149,37 @@
2345 i - edit->curs_line, 0));
2348 -static unsigned char *
2349 +static mc_wchar_t *
2350 get_paragraph (WEdit *edit, long p, long q, int indent, int *size)
2352 - unsigned char *s, *t;
2353 + mc_wchar_t *s, *t;
2354 #if 0
2355 - t = g_malloc ((q - p) + 2 * (q - p) / option_word_wrap_line_length +
2356 - 10);
2357 + t = g_malloc (((q - p) + 2 * (q - p) / option_word_wrap_line_length +
2358 + 10) * sizeof(mc_wchar_t));
2359 #else
2360 - t = g_malloc (2 * (q - p) + 100);
2361 + t = g_malloc ((2 * (q - p) + 100) * sizeof(mc_wchar_t));
2362 #endif
2363 if (!t)
2364 return 0;
2365 for (s = t; p < q; p++, s++) {
2366 if (indent)
2367 if (edit_get_byte (edit, p - 1) == '\n')
2368 +#ifndef UTF8
2369 while (strchr ("\t ", edit_get_byte (edit, p)))
2370 +#else /* UTF8 */
2371 + while (wcschr (L"\t ", edit_get_byte (edit, p)))
2372 +#endif /* UTF8 */
2373 p++;
2374 *s = edit_get_byte (edit, p);
2376 - *size = (unsigned long) s - (unsigned long) t;
2377 + *size = s - t;
2378 t[*size] = '\n';
2379 return t;
2382 -static void strip_newlines (unsigned char *t, int size)
2383 +static void strip_newlines (mc_wchar_t *t, int size)
2385 - unsigned char *p = t;
2386 + mc_wchar_t *p = t;
2387 while (size--) {
2388 *p = *p == '\n' ? ' ' : *p;
2389 p++;
2390 @@ -174,7 +196,7 @@
2392 return x += tab_width - x % tab_width;
2394 -static int line_pixel_length (unsigned char *t, long b, int l)
2395 +static int line_pixel_length (mc_wchar_t *t, long b, int l)
2397 int x = 0, c, xn = 0;
2398 for (;;) {
2399 @@ -198,7 +220,7 @@
2402 static int
2403 -next_word_start (unsigned char *t, int q, int size)
2404 +next_word_start (mc_wchar_t *t, int q, int size)
2406 int i;
2407 int saw_ws = 0;
2408 @@ -222,7 +244,7 @@
2410 /* find the start of a word */
2411 static int
2412 -word_start (unsigned char *t, int q, int size)
2413 +word_start (mc_wchar_t *t, int q, int size)
2415 int i = q;
2416 if (t[q] == ' ' || t[q] == '\t')
2417 @@ -241,7 +263,7 @@
2420 /* replaces ' ' with '\n' to properly format a paragraph */
2421 -static void format_this (unsigned char *t, int size, int indent)
2422 +static void format_this (mc_wchar_t *t, int size, int indent)
2424 int q = 0, ww;
2425 strip_newlines (t, size);
2426 @@ -269,7 +291,7 @@
2430 -static void replace_at (WEdit * edit, long q, int c)
2431 +static void replace_at (WEdit * edit, long q, mc_wint_t c)
2433 edit_cursor_move (edit, q - edit->curs1);
2434 edit_delete (edit);
2435 @@ -278,18 +300,27 @@
2437 /* replaces a block of text */
2438 static void
2439 -put_paragraph (WEdit * edit, unsigned char *t, long p, int indent, int size)
2440 +put_paragraph (WEdit * edit, mc_wchar_t *t, long p, int indent, int size)
2442 long cursor;
2443 - int i, c = 0;
2444 + int i;
2445 + mc_wchar_t c = 0;
2446 cursor = edit->curs1;
2447 if (indent)
2448 +#ifndef UTF8
2449 while (strchr ("\t ", edit_get_byte (edit, p)))
2450 +#else /* UTF8 */
2451 + while (wcschr (L"\t ", edit_get_byte (edit, p)))
2452 +#endif /* UTF8 */
2453 p++;
2454 for (i = 0; i < size; i++, p++) {
2455 if (i && indent) {
2456 if (t[i - 1] == '\n' && c == '\n') {
2457 +#ifndef UTF8
2458 while (strchr ("\t ", edit_get_byte (edit, p)))
2459 +#else /* UTF8 */
2460 + while (wcschr (L"\t ", edit_get_byte (edit, p)))
2461 +#endif /* UTF8 */
2462 p++;
2463 } else if (t[i - 1] == '\n') {
2464 long curs;
2465 @@ -301,7 +332,11 @@
2466 p = edit->curs1;
2467 } else if (c == '\n') {
2468 edit_cursor_move (edit, p - edit->curs1);
2469 +#ifndef UTF8
2470 while (strchr ("\t ", edit_get_byte (edit, p))) {
2471 +#else /* UTF8 */
2472 + while (wcschr (L"\t ", edit_get_byte (edit, p))) {
2473 +#endif /* UTF8 */
2474 edit_delete (edit);
2475 if (cursor > edit->curs1)
2476 cursor--;
2477 @@ -334,7 +369,7 @@
2479 long p, q;
2480 int size;
2481 - unsigned char *t;
2482 + mc_wchar_t *t;
2483 int indent = 0;
2484 if (option_word_wrap_line_length < 2)
2485 return;
2486 @@ -344,17 +379,25 @@
2487 q = end_paragraph (edit, force);
2488 indent = test_indent (edit, p, q);
2489 t = get_paragraph (edit, p, q, indent, &size);
2490 - if (!t)
2491 + if (!t)
2492 return;
2493 if (!force) {
2494 int i;
2495 +#ifndef UTF8
2496 if (strchr (NO_FORMAT_CHARS_START, *t)) {
2497 +#else /* UTF8 */
2498 + if (wcschr (NO_FORMAT_CHARS_START, *t)) {
2499 +#endif /* UTF8 */
2500 g_free (t);
2501 return;
2503 for (i = 0; i < size - 1; i++) {
2504 if (t[i] == '\n') {
2505 +#ifndef UTF8
2506 if (strchr (NO_FORMAT_CHARS_START "\t ", t[i + 1])) {
2507 +#else /* UTF8 */
2508 + if (wcschr (NO_FORMAT_CHARS_START "\t", t[i + 1])) {
2509 +#endif /* UTF8 */
2510 g_free (t);
2511 return;
2513 --- mc-4.6.2-pre1/src/achown.c
2514 +++ mc-4.6.2-pre1/src/achown.c
2515 @@ -584,6 +584,12 @@
2516 b_att[2] = button_new (XTRACT (6));
2517 b_user = button_new (XTRACT (5));
2518 b_group = button_new (XTRACT (4));
2519 +#ifdef UTF8
2520 + if (SLsmg_Is_Unicode) {
2521 + b_user->text = g_realloc (b_user->text, MB_CUR_MAX * 15 + 1);
2522 + b_group->text = g_realloc (b_group->text, MB_CUR_MAX * 15 + 1);
2524 +#endif
2526 add_widget (ch_dlg, b_group);
2527 add_widget (ch_dlg, b_user);
2528 --- mc-4.6.2-pre1/src/boxes.c
2529 +++ mc-4.6.2-pre1/src/boxes.c
2530 @@ -153,23 +153,23 @@
2531 display_title = _(display_title);
2532 for (i = 0; i < LIST_TYPES; i++) {
2533 displays[i] = _(displays[i]);
2534 - if ((l = strlen (displays[i])) > maxlen)
2535 + if ((l = mbstrlen (displays[i])) > maxlen)
2536 maxlen = l;
2539 - i = strlen (ok_button) + 5;
2540 - l = strlen (cancel_button) + 3;
2541 + i = mbstrlen (ok_button) + 5;
2542 + l = mbstrlen (cancel_button) + 3;
2543 l = max (i, l);
2545 i = maxlen + l + 16;
2546 if (i > DISPLAY_X)
2547 DISPLAY_X = i;
2549 - i = strlen (user_mini_status) + 13;
2550 + i = mbstrlen (user_mini_status) + 13;
2551 if (i > DISPLAY_X)
2552 DISPLAY_X = i;
2554 - i = strlen (display_title) + 10;
2555 + i = mbstrlen (display_title) + 10;
2556 if (i > DISPLAY_X)
2557 DISPLAY_X = i;
2559 @@ -288,20 +288,20 @@
2560 int maxlen = 0;
2561 for (i = SORT_TYPES - 1; i >= 0; i--) {
2562 sort_orders_names[i] = _(sort_orders[i].sort_name);
2563 - r = strlen (sort_orders_names[i]);
2564 + r = mbstrlen (sort_orders_names[i]);
2565 if (r > maxlen)
2566 maxlen = r;
2569 check_pos = maxlen + 9;
2571 - r = strlen (reverse_label) + 4;
2572 - i = strlen (case_label) + 4;
2573 + r = mbstrlen (reverse_label) + 4;
2574 + i = mbstrlen (case_label) + 4;
2575 if (i > r)
2576 r = i;
2578 - l = strlen (ok_button) + 6;
2579 - i = strlen (cancel_button) + 4;
2580 + l = mbstrlen (ok_button) + 6;
2581 + i = mbstrlen (cancel_button) + 4;
2582 if (i > l)
2583 l = i;
2585 @@ -310,7 +310,7 @@
2586 if (i > SORT_X)
2587 SORT_X = i;
2589 - i = strlen (sort_title) + 6;
2590 + i = mbstrlen (sort_title) + 6;
2591 if (i > SORT_X)
2592 SORT_X = i;
2594 @@ -408,7 +408,7 @@
2595 while (i--)
2597 conf_widgets [i].text = _(conf_widgets [i].text);
2598 - l1 = strlen (conf_widgets [i].text) + 3;
2599 + l1 = mbstrlen (conf_widgets [i].text) + 3;
2600 if (l1 > maxlen)
2601 maxlen = l1;
2603 @@ -423,8 +423,8 @@
2604 * And this for the case when buttons with some space to the right
2605 * do not fit within 2/6
2607 - l1 = strlen (conf_widgets [0].text) + 3;
2608 - i = strlen (conf_widgets [1].text) + 5;
2609 + l1 = mbstrlen (conf_widgets [0].text) + 3;
2610 + i = mbstrlen (conf_widgets [1].text) + 5;
2611 if (i > l1)
2612 l1 = i;
2614 @@ -497,11 +497,11 @@
2616 display_widgets [i].text = _(display_widgets[i].text);
2617 display_bits_str [i] = _(display_bits_str [i]);
2618 - l1 = strlen (display_bits_str [i]);
2619 + l1 = mbstrlen (display_bits_str [i]);
2620 if (l1 > maxlen)
2621 maxlen = l1;
2623 - l1 = strlen (display_widgets [2].text);
2624 + l1 = mbstrlen (display_widgets [2].text);
2625 if (l1 > maxlen)
2626 maxlen = l1;
2628 @@ -509,8 +509,8 @@
2629 display_bits.xlen = (maxlen + 5) * 6 / 4;
2631 /* See above confirm_box */
2632 - l1 = strlen (display_widgets [0].text) + 3;
2633 - i = strlen (display_widgets [1].text) + 5;
2634 + l1 = mbstrlen (display_widgets [0].text) + 3;
2635 + i = mbstrlen (display_widgets [1].text) + 5;
2636 if (i > l1)
2637 l1 = i;
2639 @@ -605,7 +605,7 @@
2641 cpname = _("&Select");
2642 add_widget (dbits_dlg,
2643 - button_new (4, DISPX - 8 - strlen (cpname), B_USER,
2644 + button_new (4, DISPX - 8 - mbstrlen (cpname), B_USER,
2645 NORMAL_BUTTON, cpname, sel_charset_button));
2647 return dbits_dlg;
2648 @@ -816,7 +816,7 @@
2649 quick_widgets [1].y_divisions =
2650 quick_widgets [0].y_divisions = Quick_input.ylen = 5;
2652 - len = strlen (quick_widgets [1].text);
2653 + len = mbstrlen (quick_widgets [1].text);
2655 quick_widgets [0].relative_x =
2656 quick_widgets [1].relative_x + len + 1;
2657 @@ -975,7 +975,7 @@
2659 job_buttons [i].name = _(job_buttons [i].name);
2661 - len = strlen (job_buttons [i].name) + 4;
2662 + len = mbstrlen (job_buttons [i].name) + 4;
2663 JOBS_X = max (JOBS_X, startx + len + 3);
2665 job_buttons [i].xpos = startx;
2666 @@ -984,7 +984,7 @@
2668 /* Last button - Ok a.k.a. Cancel :) */
2669 job_buttons [n_buttons - 1].xpos =
2670 - JOBS_X - strlen (job_buttons [n_buttons - 1].name) - 7;
2671 + JOBS_X - mbstrlen (job_buttons [n_buttons - 1].name) - 7;
2673 i18n_flag = 1;
2675 @@ -1042,7 +1042,7 @@
2677 while (i--)
2679 - l1 = strlen (labs [i] = _(labs [i]));
2680 + l1 = mbstrlen (labs [i] = _(labs [i]));
2681 if (l1 > maxlen)
2682 maxlen = l1;
2684 @@ -1052,7 +1052,7 @@
2686 for (i = sizeof(buts)/sizeof(buts[0]), l1 = 0; i--; )
2688 - l1 += strlen (buts [i] = _(buts [i]));
2689 + l1 += mbstrlen (buts [i] = _(buts [i]));
2691 l1 += 15;
2692 if (l1 > dialog_x)
2693 @@ -1061,7 +1061,7 @@
2694 ilen = dialog_x - 7 - maxlen; /* for the case of very long buttons :) */
2695 istart = dialog_x - 3 - ilen;
2697 - b2 = dialog_x - (strlen(buts[1]) + 6);
2698 + b2 = dialog_x - (mbstrlen(buts[1]) + 6);
2700 i18n_flag = 1;
2702 --- mc-4.6.2-pre1/src/dialog.c
2703 +++ mc-4.6.2-pre1/src/dialog.c
2704 @@ -166,7 +166,7 @@
2706 if (h->title) {
2707 attrset (DLG_HOT_NORMALC (h));
2708 - dlg_move (h, space, (h->cols - strlen (h->title)) / 2);
2709 + dlg_move (h, space, (h->cols - mbstrlen (h->title)) / 2);
2710 addstr (h->title);
2713 --- mc-4.6.2-pre1/src/file.c
2714 +++ mc-4.6.2-pre1/src/file.c
2715 @@ -161,15 +161,20 @@
2716 do_transform_source (FileOpContext *ctx, const char *source)
2718 size_t j, k, l, len;
2719 - const char *fnsource = x_basename (source);
2720 + char *fnsource = g_strdup (x_basename (source));
2721 int next_reg;
2722 enum CaseConvs case_conv = NO_CONV;
2723 static char fntarget[MC_MAXPATHLEN];
2725 +#ifdef UTF8
2726 + fix_utf8(fnsource);
2727 +#endif
2729 len = strlen (fnsource);
2730 j = re_match (&ctx->rx, fnsource, len, 0, &ctx->regs);
2731 if (j != len) {
2732 transform_error = FILE_SKIP;
2733 + g_free (fnsource);
2734 return NULL;
2736 for (next_reg = 1, j = 0, k = 0; j < strlen (ctx->dest_mask); j++) {
2737 @@ -213,6 +218,7 @@
2738 || ctx->regs.start[next_reg] < 0) {
2739 message (1, MSG_ERROR, _(" Invalid target mask "));
2740 transform_error = FILE_ABORT;
2741 + g_free(fnsource);
2742 return NULL;
2744 for (l = (size_t) ctx->regs.start[next_reg];
2745 @@ -227,6 +233,7 @@
2748 fntarget[k] = 0;
2749 + g_free(fnsource);
2750 return fntarget;
2753 @@ -1688,13 +1695,13 @@
2754 *dp = '\0';
2756 if (single_source) {
2757 - i = fmd_xlen - strlen (format_string) - 4;
2758 + i = fmd_xlen - mbstrlen (format_string) - 4;
2759 g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
2760 name_trunc (single_source, i));
2761 } else {
2762 g_snprintf (cmd_buf, sizeof (cmd_buf), format_string,
2763 panel->marked);
2764 - i = strlen (cmd_buf) + 6 - fmd_xlen;
2765 + i = mbstrlen (cmd_buf) + 6 - fmd_xlen;
2766 if (i > 0) {
2767 fmd_xlen += i;
2768 fmd_init_i18n (TRUE); /* to recalculate positions of child widgets */
2769 --- mc-4.6.2-pre1/src/filegui.c
2770 +++ mc-4.6.2-pre1/src/filegui.c
2771 @@ -65,6 +65,7 @@
2772 #include "filegui.h"
2773 #include "key.h" /* get_event */
2774 #include "util.h" /* strip_password() */
2775 +#include "tty.h"
2777 /* }}} */
2779 @@ -563,8 +564,8 @@
2780 * longest of "Overwrite..." labels
2781 * (assume "Target date..." are short enough)
2783 - l1 = max (strlen (rd_widgets[6].text),
2784 - strlen (rd_widgets[11].text));
2785 + l1 = max (mbstrlen (rd_widgets[6].text),
2786 + mbstrlen (rd_widgets[11].text));
2788 /* longest of button rows */
2789 i = sizeof (rd_widgets) / sizeof (rd_widgets[0]);
2790 @@ -575,7 +576,7 @@
2791 l2 = max (l2, l);
2792 l = 0;
2794 - l += strlen (rd_widgets[i].text) + 4;
2795 + l += mbstrlen (rd_widgets[i].text) + 4;
2798 l2 = max (l2, l); /* last row */
2799 @@ -593,12 +594,12 @@
2800 l = l1;
2802 rd_widgets[i].xpos = l;
2803 - l += strlen (rd_widgets[i].text) + 4;
2804 + l += mbstrlen (rd_widgets[i].text) + 4;
2807 /* Abort button is centered */
2808 rd_widgets[1].xpos =
2809 - (rd_xlen - strlen (rd_widgets[1].text) - 3) / 2;
2810 + (rd_xlen - mbstrlen (rd_widgets[1].text) - 3) / 2;
2812 #endif /* ENABLE_NLS */
2814 @@ -617,7 +618,7 @@
2816 ADD_RD_LABEL (ui, 0,
2817 name_trunc (ui->replace_filename,
2818 - rd_trunc - strlen (rd_widgets[0].text)), 0);
2819 + rd_trunc - mbstrlen (rd_widgets[0].text)), 0);
2820 ADD_RD_BUTTON (1);
2822 ADD_RD_BUTTON (2);
2823 @@ -804,36 +805,36 @@
2824 if (fmd_widgets[i].text[0] != '\0')
2825 fmd_widgets[i].text = _(fmd_widgets[i].text);
2827 - len = strlen (fmd_widgets[FMCB11].text)
2828 - + strlen (fmd_widgets[FMCB21].text) + 15;
2829 + len = mbstrlen (fmd_widgets[FMCB11].text)
2830 + + mbstrlen (fmd_widgets[FMCB21].text) + 15;
2831 fmd_xlen = max (fmd_xlen, len);
2833 - len = strlen (fmd_widgets[FMCB12].text)
2834 - + strlen (fmd_widgets[FMCB22].text) + 15;
2835 + len = mbstrlen (fmd_widgets[FMCB12].text)
2836 + + mbstrlen (fmd_widgets[FMCB22].text) + 15;
2837 fmd_xlen = max (fmd_xlen, len);
2839 - len = strlen (fmd_widgets[FMBRGT].text)
2840 - + strlen (fmd_widgets[FMBLFT].text) + 11;
2841 + len = mbstrlen (fmd_widgets[FMBRGT].text)
2842 + + mbstrlen (fmd_widgets[FMBLFT].text) + 11;
2844 #ifdef FMBMID
2845 - len += strlen (fmd_widgets[FMBMID].text) + 6;
2846 + len += mbstrlen (fmd_widgets[FMBMID].text) + 6;
2847 #endif
2849 fmd_xlen = max (fmd_xlen, len + 4);
2851 len = (fmd_xlen - (len + 6)) / 2;
2852 i = fmd_widgets[FMBLFT].relative_x = len + 3;
2853 - i += strlen (fmd_widgets[FMBLFT].text) + 8;
2854 + i += mbstrlen (fmd_widgets[FMBLFT].text) + 8;
2856 #ifdef FMBMID
2857 fmd_widgets[FMBMID].relative_x = i;
2858 - i += strlen (fmd_widgets[FMBMID].text) + 6;
2859 + i += mbstrlen (fmd_widgets[FMBMID].text) + 6;
2860 #endif
2862 fmd_widgets[FMBRGT].relative_x = i;
2864 #define chkbox_xpos(i) \
2865 - fmd_widgets [i].relative_x = fmd_xlen - strlen (fmd_widgets [i].text) - 6
2866 + fmd_widgets [i].relative_x = fmd_xlen - mbstrlen (fmd_widgets [i].text) - 6
2868 chkbox_xpos (FMCB0);
2869 chkbox_xpos (FMCB21);
2870 @@ -855,7 +856,7 @@
2872 char *
2873 file_mask_dialog (FileOpContext *ctx, FileOperation operation, const char *text,
2874 - const char *def_text, int only_one, int *do_background)
2875 + const char *def_text_orig, int only_one, int *do_background)
2877 int source_easy_patterns = easy_patterns;
2878 char *source_mask, *orig_mask, *dest_dir, *tmpdest;
2879 @@ -864,12 +865,20 @@
2880 struct stat buf;
2881 int val;
2882 QuickDialog Quick_input;
2884 + char *def_text;
2885 g_return_val_if_fail (ctx != NULL, NULL);
2887 + def_text = g_strdup(def_text_orig);
2889 #if 0
2890 message (1, __FUNCTION__, "text = `%s' \n def_text = `%s'", text,
2891 def_text);
2892 #endif
2894 +#ifdef UTF8
2895 + fix_utf8(def_text);
2896 +#endif
2898 fmd_init_i18n (FALSE);
2900 /* Set up the result pointers */
2901 @@ -928,6 +937,7 @@
2902 orig_mask = source_mask;
2903 if (!dest_dir || !*dest_dir) {
2904 g_free (source_mask);
2905 + g_free(def_text);
2906 return dest_dir;
2908 if (source_easy_patterns) {
2909 @@ -981,5 +991,6 @@
2911 if (val == B_USER)
2912 *do_background = 1;
2913 + g_free(def_text);
2914 return dest_dir;
2916 --- mc-4.6.2-pre1/src/find.c
2917 +++ mc-4.6.2-pre1/src/find.c
2918 @@ -217,7 +217,7 @@
2919 int l1, maxlen = 0;
2921 while (i--) {
2922 - l1 = strlen (labs[i] = _(labs[i]));
2923 + l1 = mbstrlen (labs[i] = _(labs[i]));
2924 if (l1 > maxlen)
2925 maxlen = l1;
2927 @@ -226,7 +226,7 @@
2928 FIND_X = i;
2930 for (i = sizeof (buts) / sizeof (buts[0]), l1 = 0; i--;) {
2931 - l1 += strlen (buts[i] = _(buts[i]));
2932 + l1 += mbstrlen (buts[i] = _(buts[i]));
2934 l1 += 21;
2935 if (l1 > FIND_X)
2936 @@ -235,8 +235,8 @@
2937 ilen = FIND_X - 7 - maxlen; /* for the case of very long buttons :) */
2938 istart = FIND_X - 3 - ilen;
2940 - b1 = b0 + strlen (buts[0]) + 7;
2941 - b2 = FIND_X - (strlen (buts[2]) + 6);
2942 + b1 = b0 + mbstrlen (buts[0]) + 7;
2943 + b2 = FIND_X - (mbstrlen (buts[2]) + 6);
2945 i18n_flag = 1;
2946 case_label = _(case_label);
2947 @@ -863,7 +863,7 @@
2948 if (!i18n_flag) {
2949 register int i = sizeof (fbuts) / sizeof (fbuts[0]);
2950 while (i--)
2951 - fbuts[i].len = strlen (fbuts[i].text = _(fbuts[i].text)) + 3;
2952 + fbuts[i].len = mbstrlen (fbuts[i].text = _(fbuts[i].text)) + 3;
2953 fbuts[2].len += 2; /* DEFPUSH_BUTTON */
2954 i18n_flag = 1;
2956 @@ -1028,7 +1028,7 @@
2958 if (!next_free) /* first turn i.e clean old list */
2959 panel_clean_dir (current_panel);
2960 - list->list[next_free].fnamelen = strlen (name);
2961 + list->list[next_free].fnamelen = mbstrlen (name);
2962 list->list[next_free].fname = name;
2963 list->list[next_free].f.marked = 0;
2964 list->list[next_free].f.link_to_dir = link_to_dir;
2965 --- mc-4.6.2-pre1/src/help.c
2966 +++ mc-4.6.2-pre1/src/help.c
2967 @@ -447,10 +447,28 @@
2968 #ifndef HAVE_SLANG
2969 addch (acs_map [c]);
2970 #else
2971 +#if defined(UTF8) && SLANG_VERSION < 20000
2972 + SLsmg_draw_object (h->y + line + 2, h->x + col + 2, acs_map [c]);
2973 +#else
2974 SLsmg_draw_object (h->y + line + 2, h->x + col + 2, c);
2975 +#endif /* UTF8 */
2976 #endif
2977 + } else {
2978 +#ifdef UTF8
2979 + if (SLsmg_Is_Unicode) {
2980 + int len;
2981 + mbstate_t mbs;
2982 + wchar_t wc;
2983 + memset (&mbs, 0, sizeof (mbs));
2984 + len = mbrtowc(&wc, p, MB_CUR_MAX, &mbs);
2985 + if (len <= 0) len = 1; /* skip broken multibyte chars */
2987 + SLsmg_write_nwchars(&wc, 1);
2988 + p += len - 1;
2989 } else
2990 +#endif
2991 addch (c);
2993 col++;
2994 break;
2996 @@ -803,6 +821,12 @@
2997 message (1, MSG_ERROR, _(" Cannot open file %s \n %s "), filename ? filename : hlpfile,
2998 unix_error_string (errno));
3000 + else
3002 + char *conv = utf8_to_local(data);
3003 + g_free(data);
3004 + data = conv;
3007 if (!filename)
3008 g_free (hlpfile);
3009 --- mc-4.6.2-pre1/src/hotlist.c
3010 +++ mc-4.6.2-pre1/src/hotlist.c
3011 @@ -563,7 +563,7 @@
3013 row = hotlist_but [i].y;
3014 ++count [row];
3015 - len [row] += strlen (hotlist_but [i].text) + 5;
3016 + len [row] += mbstrlen (hotlist_but [i].text) + 5;
3017 if (hotlist_but [i].flags == DEFPUSH_BUTTON)
3018 len [row] += 2;
3020 @@ -588,12 +588,12 @@
3021 /* not first int the row */
3022 if (!strcmp (hotlist_but [i].text, cancel_but))
3023 hotlist_but [i].x =
3024 - cols - strlen (hotlist_but [i].text) - 13;
3025 + cols - mbstrlen (hotlist_but [i].text) - 13;
3026 else
3027 hotlist_but [i].x = cur_x [row];
3030 - cur_x [row] += strlen (hotlist_but [i].text) + 2
3031 + cur_x [row] += mbstrlen (hotlist_but [i].text) + 2
3032 + (hotlist_but [i].flags == DEFPUSH_BUTTON ? 5 : 3);
3035 @@ -834,7 +834,7 @@
3036 for (i = 0; i < 3; i++)
3038 qw [i].text = _(qw [i].text);
3039 - l[i] = strlen (qw [i].text) + 3;
3040 + l[i] = mbstrlen (qw [i].text) + 3;
3042 space = (len - 4 - l[0] - l[1] - l[2]) / 4;
3044 @@ -883,7 +883,7 @@
3046 msglen(text1, &lines1, &cols1);
3047 msglen(text2, &lines2, &cols2);
3048 - len = max ((int) strlen (header), cols1);
3049 + len = max ((int) mbstrlen (header), cols1);
3050 len = max (len, cols2) + 4;
3051 len = max (len, 64);
3053 @@ -979,7 +979,7 @@
3054 #endif /* ENABLE_NLS */
3056 msglen (label, &lines, &cols);
3057 - len = max ((int) strlen (header), cols) + 4;
3058 + len = max ((int) mbstrlen (header), cols) + 4;
3059 len = max (len, 64);
3061 #ifdef ENABLE_NLS
3062 @@ -1035,7 +1035,7 @@
3064 char *prompt, *label;
3065 const char *cp = _("Label for \"%s\":");
3066 - int l = strlen (cp);
3067 + int l = mbstrlen (cp);
3068 char *label_string = g_strdup (current_panel->cwd);
3070 strip_password (label_string, 1);
3071 --- mc-4.6.2-pre1/src/layout.c
3072 +++ mc-4.6.2-pre1/src/layout.c
3073 @@ -366,36 +366,36 @@
3075 while (i--) {
3076 s_split_direction[i] = _(s_split_direction[i]);
3077 - l1 = strlen (s_split_direction[i]) + 7;
3078 + l1 = mbstrlen (s_split_direction[i]) + 7;
3079 if (l1 > first_width)
3080 first_width = l1;
3083 for (i = 0; i <= 8; i++) {
3084 check_options[i].text = _(check_options[i].text);
3085 - l1 = strlen (check_options[i].text) + 7;
3086 + l1 = mbstrlen (check_options[i].text) + 7;
3087 if (l1 > first_width)
3088 first_width = l1;
3091 - l1 = strlen (title1) + 1;
3092 + l1 = mbstrlen (title1) + 1;
3093 if (l1 > first_width)
3094 first_width = l1;
3096 - l1 = strlen (title2) + 1;
3097 + l1 = mbstrlen (title2) + 1;
3098 if (l1 > first_width)
3099 first_width = l1;
3102 - second_width = strlen (title3) + 1;
3103 + second_width = mbstrlen (title3) + 1;
3104 for (i = 0; i < 6; i++) {
3105 check_options[i].text = _(check_options[i].text);
3106 - l1 = strlen (check_options[i].text) + 7;
3107 + l1 = mbstrlen (check_options[i].text) + 7;
3108 if (l1 > second_width)
3109 second_width = l1;
3111 if (console_flag) {
3112 - l1 = strlen (output_lines_label) + 13;
3113 + l1 = mbstrlen (output_lines_label) + 13;
3114 if (l1 > second_width)
3115 second_width = l1;
3117 @@ -409,14 +409,14 @@
3119 * Now the last thing to do - properly space buttons...
3121 - l1 = 11 + strlen (ok_button) /* 14 - all brackets and inner space */
3122 - +strlen (save_button) /* notice: it is 3 char less because */
3123 - +strlen (cancel_button); /* of '&' char in button text */
3124 + l1 = 11 + mbstrlen (ok_button) /* 14 - all brackets and inner space */
3125 + +mbstrlen (save_button) /* notice: it is 3 char less because */
3126 + +mbstrlen (cancel_button); /* of '&' char in button text */
3128 i = (first_width + second_width - l1) / 4;
3129 b1 = 5 + i;
3130 - b2 = b1 + strlen (ok_button) + i + 6;
3131 - b3 = b2 + strlen (save_button) + i + 4;
3132 + b2 = b1 + mbstrlen (ok_button) + i + 6;
3133 + b3 = b2 + mbstrlen (save_button) + i + 4;
3135 i18n_layt_flag = 1;
3137 @@ -684,7 +684,7 @@
3138 panel_do_cols (0);
3139 panel_do_cols (1);
3141 - promptl = strlen (prompt);
3142 + promptl = mbstrlen (prompt);
3144 widget_set_size (&the_menubar->widget, 0, 0, 1, COLS);
3146 --- mc-4.6.2-pre1/src/learn.c
3147 +++ mc-4.6.2-pre1/src/learn.c
3148 @@ -237,7 +237,7 @@
3149 learn_but[0].x = 78 / 2 + 4;
3151 learn_but[1].text = _(learn_but[1].text);
3152 - learn_but[1].x = 78 / 2 - (strlen (learn_but[1].text) + 9);
3153 + learn_but[1].x = 78 / 2 - (mbstrlen (learn_but[1].text) + 9);
3155 learn_title = _(learn_title);
3156 i18n_flag = 1;
3157 --- mc-4.6.2-pre1/src/main.c
3158 +++ mc-4.6.2-pre1/src/main.c
3159 @@ -704,7 +704,7 @@
3160 int prompt_len;
3162 tmp_prompt = strip_ctrl_codes (subshell_prompt);
3163 - prompt_len = strlen (tmp_prompt);
3164 + prompt_len = mbstrlen (tmp_prompt);
3166 /* Check for prompts too big */
3167 if (COLS > 8 && prompt_len > COLS - 8) {
3168 @@ -1610,7 +1610,11 @@
3169 if (xterm_flag && xterm_title) {
3170 p = s = g_strdup (strip_home_and_password (current_panel->cwd));
3171 do {
3172 +#ifndef UTF8
3173 if (!is_printable ((unsigned char) *s))
3174 +#else /* UTF8 */
3175 + if (*(unsigned char *)s < ' ')
3176 +#endif /* UTF8 */
3177 *s = '?';
3178 } while (*++s);
3179 fprintf (stdout, "\33]0;mc - %s\7", p);
3180 --- mc-4.6.2-pre1/src/menu.c
3181 +++ mc-4.6.2-pre1/src/menu.c
3182 @@ -22,6 +22,7 @@
3183 #include <string.h>
3185 #include <sys/types.h>
3186 +#include <wchar.h>
3188 #include "global.h"
3189 #include "tty.h"
3190 @@ -53,35 +54,95 @@
3192 Menu *menu;
3193 const char *cp;
3194 + int wlen = 0;
3195 + mbstate_t s;
3197 menu = (Menu *) g_malloc (sizeof (*menu));
3198 menu->count = count;
3199 menu->max_entry_len = 20;
3200 menu->entries = entries;
3201 + menu->name = g_strdup (name);
3202 + menu_scan_hotkey (menu);
3203 +#ifdef UTF8
3204 + menu->wentries = NULL;
3205 + menu->wname = NULL;
3206 + if (SLsmg_Is_Unicode) {
3207 + const char *str = menu->name;
3208 + memset (&s, 0, sizeof (s));
3209 + wlen = mbsrtowcs (NULL, &str, -1, &s);
3210 + if (wlen > 0)
3211 + ++wlen;
3212 + else {
3213 + wlen = 0;
3214 + memset (&s, 0, sizeof (s));
3217 +#endif
3219 if (entries != (menu_entry*) NULL) {
3220 register menu_entry* mp;
3221 for (mp = entries; count--; mp++) {
3222 if (mp->text[0] != '\0') {
3223 + int len;
3224 #ifdef ENABLE_NLS
3225 mp->text = _(mp->text);
3226 #endif /* ENABLE_NLS */
3227 cp = strchr (mp->text,'&');
3228 +#ifdef UTF8
3229 + if (SLsmg_Is_Unicode) {
3230 + len = mbstrlen(mp->text) + 1;
3231 + wlen += len;
3232 + menu->max_entry_len = max (len - 1, menu->max_entry_len);
3233 + } else
3234 +#endif
3235 + len = strlen (mp->text);
3237 if (cp != NULL && *(cp+1) != '\0') {
3238 mp->hot_key = tolower ((unsigned char) *(cp+1));
3239 - menu->max_entry_len = max ((int) (strlen (mp->text) - 1),
3240 - menu->max_entry_len);
3241 + menu->max_entry_len = max (len - 1, menu->max_entry_len);
3242 } else {
3243 - menu->max_entry_len = max ((int) strlen (mp->text),
3244 - menu->max_entry_len);
3245 + menu->max_entry_len = max (len, menu->max_entry_len);
3251 - menu->name = g_strdup (name);
3252 - menu_scan_hotkey(menu);
3253 +#ifdef UTF8
3254 + if (wlen) {
3255 + wchar_t *wp;
3256 + const char *str;
3257 + int len;
3259 + menu->wentries = (wchar_t **)
3260 + g_malloc (sizeof (wchar_t *) * menu->count
3261 + + wlen * sizeof (wchar_t));
3262 + wp = (wchar_t *) (menu->wentries + menu->count);
3263 + str = menu->name;
3264 + len = mbsrtowcs (wp, &str, wlen, &s);
3265 + if (len > 0) {
3266 + menu->wname = wp;
3267 + wlen -= len + 1;
3268 + wp += len + 1;
3269 + } else
3270 + memset (&s, 0, sizeof (s));
3271 + if (menu->entries != NULL)
3272 + for (count = 0; count < menu->count; ++count)
3273 + if (menu->entries[count].text[0] != '\0') {
3274 + str = menu->entries[count].text;
3275 + menu->wentries[count] = wp;
3276 + len = mbsrtowcs (wp, &str, wlen, &s);
3277 + if (len > 0) {
3278 + wlen -= len + 1;
3279 + wp += len + 1;
3280 + } else {
3281 + memset (&s, 0, sizeof (s));
3282 + *wp++ = L'\0';
3283 + --wlen;
3287 +#endif
3289 menu->start_x = 0;
3290 menu->help_node = g_strdup (help_node);
3291 return menu;
3292 @@ -112,8 +173,26 @@
3293 const char *text;
3295 addch((unsigned char)menu->entries [idx].first_letter);
3296 - for (text = menu->entries [idx].text; *text; text++)
3298 +#ifdef UTF8
3299 + if (menu->wentries) {
3300 + wchar_t *wtext, *wp;
3302 + for (wtext = wp = menu->wentries [idx]; *wtext; wtext++) {
3303 + if (*wtext == L'&') {
3304 + if (wtext > wp)
3305 + SLsmg_write_nwchars (wp, wtext - wp);
3306 + attrset (color == MENU_SELECTED_COLOR ?
3307 + MENU_HOTSEL_COLOR : MENU_HOT_COLOR);
3308 + SLsmg_write_nwchars (++wtext, 1);
3309 + attrset (color);
3310 + wp = wtext + 1;
3313 + if (wtext > wp)
3314 + SLsmg_write_nwchars (wp, wtext - wp);
3315 + } else
3316 +#endif
3317 + for (text = menu->entries [idx].text; *text; text++) {
3318 if (*text != '&')
3319 addch(*text);
3320 else {
3321 @@ -122,7 +201,7 @@
3322 addch(*(++text));
3323 attrset(color);
3328 widget_move (&menubar->widget, y, x + 1);
3330 @@ -168,6 +247,12 @@
3331 if (menubar->active)
3332 attrset(i == menubar->selected?MENU_SELECTED_COLOR:SELECTED_COLOR);
3333 widget_move (&menubar->widget, 0, menubar->menu [i]->start_x);
3334 +#ifdef UTF8
3335 + if (menubar->menu [i]->wname)
3336 + SLsmg_write_nwchars (menubar->menu [i]->wname,
3337 + wcslen (menubar->menu [i]->wname));
3338 + else
3339 +#endif
3340 tty_printf ("%s", menubar->menu [i]->name);
3343 @@ -493,7 +578,13 @@
3345 for (i = 0; i < items; i++)
3347 - int len = strlen(menubar->menu[i]->name);
3348 + int len;
3349 +#ifdef UTF8
3350 + if (menubar->menu[i]->wname)
3351 + len = wcslen (menubar->menu[i]->wname);
3352 + else
3353 +#endif
3354 + len = strlen(menubar->menu[i]->name);
3355 menubar->menu[i]->start_x = start_x;
3356 start_x += len + gap;
3358 @@ -506,7 +597,13 @@
3359 for (i = 0; i < items; i++)
3361 /* preserve length here, to be used below */
3362 - gap -= (menubar->menu[i]->start_x = strlen(menubar->menu[i]->name));
3363 +#ifdef UTF8
3364 + if (menubar->menu[i]->wname)
3365 + menubar->menu[i]->start_x = wcslen (menubar->menu[i]->wname);
3366 + else
3367 +#endif
3368 + menubar->menu[i]->start_x = strlen (menubar->menu[i]->name);
3369 + gap -= menubar->menu[i]->start_x;
3372 gap /= (items - 1);
3373 @@ -530,6 +627,9 @@
3374 void
3375 destroy_menu (Menu *menu)
3377 +#ifdef UTF8
3378 + g_free (menu->wentries);
3379 +#endif
3380 g_free (menu->name);
3381 g_free (menu->help_node);
3382 g_free (menu);
3383 --- mc-4.6.2-pre1/src/menu.h
3384 +++ mc-4.6.2-pre1/src/menu.h
3385 @@ -21,6 +21,8 @@
3386 menu_entry *entries;
3387 int start_x; /* position relative to menubar start */
3388 char *help_node;
3389 + wchar_t **wentries;
3390 + wchar_t *wname;
3391 } Menu;
3393 extern int menubar_visible;
3394 --- mc-4.6.2-pre1/src/myslang.h
3395 +++ mc-4.6.2-pre1/src/myslang.h
3396 @@ -11,6 +11,16 @@
3397 #endif /* HAVE_SLANG_SLANG_H */
3398 #endif
3400 +#if SLANG_VERSION >= 20000
3401 +#define UTF8 1
3402 +#define SLsmg_Is_Unicode SLsmg_is_utf8_mode()
3403 +void SLsmg_write_nwchars(wchar_t *s, size_t n);
3404 +#endif
3406 +#ifdef UTF8
3407 +# include <wchar.h>
3408 +#endif
3410 enum {
3411 KEY_BACKSPACE = 400,
3412 KEY_END, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT,
3413 --- mc-4.6.2-pre1/src/option.c
3414 +++ mc-4.6.2-pre1/src/option.c
3415 @@ -123,12 +123,12 @@
3416 title2 = _(" Pause after run... ");
3417 title3 = _(" Other options ");
3419 - first_width = strlen (title1) + 1;
3420 - second_width = strlen (title3) + 1;
3421 + first_width = mbstrlen (title1) + 1;
3422 + second_width = mbstrlen (title3) + 1;
3424 for (i = 0; check_options[i].text; i++) {
3425 check_options[i].text = _(check_options[i].text);
3426 - l1 = strlen (check_options[i].text) + 7;
3427 + l1 = mbstrlen (check_options[i].text) + 7;
3428 if (i >= OTHER_OPTIONS) {
3429 if (l1 > first_width)
3430 first_width = l1;
3431 @@ -141,23 +141,23 @@
3432 i = PAUSE_OPTIONS;
3433 while (i--) {
3434 pause_options[i] = _(pause_options[i]);
3435 - l1 = strlen (pause_options[i]) + 7;
3436 + l1 = mbstrlen (pause_options[i]) + 7;
3437 if (l1 > first_width)
3438 first_width = l1;
3441 - l1 = strlen (title2) + 1;
3442 + l1 = mbstrlen (title2) + 1;
3443 if (l1 > first_width)
3444 first_width = l1;
3446 - l1 = 11 + strlen (ok_button)
3447 - + strlen (save_button)
3448 - + strlen (cancel_button);
3449 + l1 = 11 + mbstrlen (ok_button)
3450 + + mbstrlen (save_button)
3451 + + mbstrlen (cancel_button);
3453 i = (first_width + second_width - l1) / 4;
3454 b1 = 5 + i;
3455 - b2 = b1 + strlen (ok_button) + i + 6;
3456 - b3 = b2 + strlen (save_button) + i + 4;
3457 + b2 = b1 + mbstrlen (ok_button) + i + 6;
3458 + b3 = b2 + mbstrlen (save_button) + i + 4;
3460 i18n_config_flag = 1;
3462 --- mc-4.6.2-pre1/src/panelize.c
3463 +++ mc-4.6.2-pre1/src/panelize.c
3464 @@ -127,7 +127,7 @@
3465 i = sizeof (panelize_but) / sizeof (panelize_but[0]);
3466 while (i--) {
3467 panelize_but[i].text = _(panelize_but[i].text);
3468 - maxlen += strlen (panelize_but[i].text) + 5;
3469 + maxlen += mbstrlen (panelize_but[i].text) + 5;
3471 maxlen += 10;
3473 @@ -136,11 +136,11 @@
3474 panelize_cols = max (panelize_cols, maxlen);
3476 panelize_but[2].x =
3477 - panelize_but[3].x + strlen (panelize_but[3].text) + 7;
3478 + panelize_but[3].x + mbstrlen (panelize_but[3].text) + 7;
3479 panelize_but[1].x =
3480 - panelize_but[2].x + strlen (panelize_but[2].text) + 5;
3481 + panelize_but[2].x + mbstrlen (panelize_but[2].text) + 5;
3482 panelize_but[0].x =
3483 - panelize_cols - strlen (panelize_but[0].text) - 8 - BX;
3484 + panelize_cols - mbstrlen (panelize_but[0].text) - 8 - BX;
3486 #endif /* ENABLE_NLS */
3488 --- mc-4.6.2-pre1/src/screen.c
3489 +++ mc-4.6.2-pre1/src/screen.c
3490 @@ -171,21 +171,56 @@
3491 static const char *
3492 string_file_name (file_entry *fe, int len)
3494 - static char buffer [MC_MAXPATHLEN + 1];
3495 size_t i;
3497 - for (i = 0; i < sizeof(buffer) - 1; i++) {
3498 - char c;
3499 +#ifdef UTF8
3500 + static char buffer [BUF_SMALL * 4];
3501 + mbstate_t s;
3502 + int mbmax = MB_CUR_MAX;
3503 + const char *str = fe->fname;
3505 - c = fe->fname[i];
3506 + memset (&s, 0, sizeof (s));
3507 +#else
3508 + static char buffer [BUF_SMALL];
3509 +#endif
3511 - if (!c)
3512 - break;
3513 +#ifdef UTF8
3514 + if (SLsmg_Is_Unicode)
3515 + for (i = 0; i < sizeof (buffer) - 1; i++) {
3516 + wchar_t wc;
3517 + int len;
3519 - if (!is_printable(c))
3520 - c = '?';
3521 + len = mbrtowc (&wc, str, mbmax, &s);
3522 + if (!len)
3523 + break;
3524 + if (len < 0) {
3525 + memset (&s, 0, sizeof (s));
3526 + buffer[i] = '?';
3527 + str++;
3528 + continue;
3530 + if (!is_printable (wc)) {
3531 + buffer[i] = '?';
3532 + str++;
3533 + continue;
3535 + if (i >= sizeof (buffer) - len)
3536 + break;
3537 + memcpy (buffer + i, str, len);
3538 + i += len - 1;
3539 + str += len;
3540 + } else
3541 +#endif
3542 + for (i = 0; i < sizeof(buffer) - 1; i++) {
3543 + char c;
3545 + c = fe->fname[i];
3547 - buffer[i] = c;
3548 + if (!c) break;
3550 + if (!is_printable(c)) c = '?';
3552 + buffer[i] = c;
3555 buffer[i] = 0;
3556 @@ -450,42 +485,6 @@
3557 { "dot", 1, 0, J_RIGHT, " ", 0, string_dot, NULL },
3560 -static char *
3561 -to_buffer (char *dest, int just_mode, int len, const char *txt)
3563 - int txtlen = strlen (txt);
3564 - int still, over;
3566 - /* Fill buffer with spaces */
3567 - memset (dest, ' ', len);
3569 - still = (over=(txtlen > len)) ? (txtlen - len) : (len - txtlen);
3571 - switch (HIDE_FIT(just_mode)){
3572 - case J_LEFT:
3573 - still = 0;
3574 - break;
3575 - case J_CENTER:
3576 - still /= 2;
3577 - break;
3578 - case J_RIGHT:
3579 - default:
3580 - break;
3583 - if (over){
3584 - if (IS_FIT(just_mode))
3585 - strcpy (dest, name_trunc(txt, len));
3586 - else
3587 - strncpy (dest, txt+still, len);
3588 - } else
3589 - strncpy (dest+still, txt, txtlen);
3591 - dest[len] = '\0';
3593 - return (dest + len);
3596 static int
3597 file_compute_color (int attr, file_entry *fe)
3599 @@ -539,14 +538,18 @@
3601 /* Formats the file number file_index of panel in the buffer dest */
3602 static void
3603 -format_file (char *dest, int limit, WPanel *panel, int file_index, int width, int attr, int isstatus)
3604 +format_file (WPanel *panel, int file_index, int width, int attr, int isstatus)
3606 int color, length, empty_line;
3607 const char *txt;
3608 - char *old_pos;
3609 - char *cdest = dest;
3610 format_e *format, *home;
3611 file_entry *fe;
3612 +#ifdef UTF8
3613 + char buffer[BUF_MEDIUM * sizeof (wchar_t)];
3614 +#else
3615 + char buffer[BUF_MEDIUM];
3616 +#endif
3617 + int txtwidth = 0;
3619 length = 0;
3620 empty_line = (file_index >= panel->count);
3621 @@ -564,34 +567,137 @@
3622 break;
3624 if (format->string_fn){
3625 - int len;
3626 + int len, still, over, perm, txtlen, wide;
3628 if (empty_line)
3629 txt = " ";
3630 else
3631 txt = (*format->string_fn)(fe, format->field_len);
3633 - old_pos = cdest;
3635 len = format->field_len;
3636 if (len + length > width)
3637 len = width - length;
3638 - if (len + (cdest - dest) > limit)
3639 - len = limit - (cdest - dest);
3640 + if (len >= BUF_MEDIUM)
3641 + len = BUF_MEDIUM - 1;
3642 if (len <= 0)
3643 break;
3644 - cdest = to_buffer (cdest, format->just_mode, len, txt);
3645 - length += len;
3647 - attrset (color);
3648 + perm = 0;
3649 + if (permission_mode) {
3650 + if (!strcmp(format->id, "perm"))
3651 + perm = 1;
3652 + else if (!strcmp(format->id, "mode"))
3653 + perm = 2;
3656 - if (permission_mode && !strcmp(format->id, "perm"))
3657 - add_permission_string (old_pos, format->field_len, fe, attr, color, 0);
3658 - else if (permission_mode && !strcmp(format->id, "mode"))
3659 - add_permission_string (old_pos, format->field_len, fe, attr, color, 1);
3660 - else
3661 - addstr (old_pos);
3662 + wide = 0;
3663 +#ifdef UTF8
3664 + if (SLsmg_Is_Unicode && !empty_line && !perm) {
3665 + mbstate_t s;
3666 + const char *str = txt;
3668 + memset (&s, 0, sizeof (s));
3669 + txtlen = mbsrtowcs ((wchar_t *) buffer, &str,
3670 + sizeof (buffer) / sizeof (wchar_t), &s);
3671 + if (txtlen < 0) {
3672 + txt = " ";
3673 + txtlen = 1;
3674 + } else {
3675 + wide = 1;
3676 + txtwidth = wcswidth((wchar_t*)buffer, txtlen);
3678 + } else
3679 +#endif
3681 + txtlen = mbstrlen (txt);
3682 + txtwidth = txtlen;
3685 + over = txtwidth > len;
3686 + still = over ? txtlen - len : len - txtlen;
3688 + switch (HIDE_FIT(format->just_mode)) {
3689 + case J_LEFT:
3690 + still = 0;
3691 + break;
3692 + case J_CENTER:
3693 + still /= 2;
3694 + break;
3695 + case J_RIGHT:
3696 + default:
3697 + break;
3700 + attrset (color);
3702 + if (wide) {
3703 +#ifdef UTF8
3704 + if (over) {
3705 + if (IS_FIT (format->just_mode)) {
3706 + int n1 = 0;
3707 + int width1 = 0;
3708 + int n2 = 0;
3709 + int width2 = 0;
3710 + int len1 = len / 2;
3711 + int len2;
3713 + while (1) {
3714 + int w = wcwidth(((wchar_t *) buffer)[n1]);
3715 + if (width1 + w <= len1) {
3716 + width1 += w;
3717 + n1++;
3719 + else
3720 + break;
3722 + len2 = len - width1 - 1;
3724 + while (1) {
3725 + int w = wcwidth(((wchar_t *) buffer)[txtlen - n2 - 1]);
3726 + if (width2 + w <= len2) {
3727 + width2 += w;
3728 + n2++;
3730 + else
3731 + break;
3735 + SLsmg_write_nwchars ((wchar_t *) buffer, n1);
3736 + SLsmg_write_nwchars (L"~", 1);
3737 + printw ("%*s", len - width1 - width2 - 1, "");
3738 + SLsmg_write_nwchars (((wchar_t *) buffer)
3739 + + txtlen - n2, n2);
3740 + } else
3741 + SLsmg_write_nwchars ((wchar_t *) buffer, len);
3742 + } else {
3743 + printw ("%*s", still, "");
3744 + SLsmg_write_nwchars ((wchar_t *) buffer, txtlen);
3745 + printw ("%*s", len - txtwidth - still, "");
3747 +#endif
3748 + } else {
3749 + if (over) {
3750 + if (IS_FIT (format->just_mode))
3751 + strcpy (buffer, name_trunc(txt, len));
3752 + else
3753 + memcpy (buffer, txt + still, len);
3754 + } else {
3755 + memset (buffer, ' ', still);
3756 + memcpy (buffer + still, txt, txtlen);
3757 + memset (buffer + still + txtlen, ' ',
3758 + len - txtlen - still);
3760 + buffer[len] = '\0';
3762 + if (perm)
3763 + add_permission_string (buffer, format->field_len, fe,
3764 + attr, color, perm - 1);
3765 + else
3766 + addstr (buffer);
3769 + length += len;
3770 } else {
3771 if (attr == SELECTED || attr == MARKED_SELECTED)
3772 attrset (SELECTED_COLOR);
3773 @@ -614,7 +720,6 @@
3775 int second_column = 0;
3776 int width, offset;
3777 - char buffer [BUF_MEDIUM];
3779 offset = 0;
3780 if (!isstatus && panel->split){
3781 @@ -643,7 +748,7 @@
3782 widget_move (&panel->widget, file_index - panel->top_file + 2, 1);
3785 - format_file (buffer, sizeof(buffer), panel, file_index, width, attr, isstatus);
3786 + format_file (panel, file_index, width, attr, isstatus);
3788 if (!isstatus && panel->split){
3789 if (second_column)
3790 @@ -692,7 +797,7 @@
3791 ngettext("%s in %d file", "%s in %d files", panel->marked),
3792 b_bytes, panel->marked);
3794 - if ((int) strlen (buffer) > cols-2){
3795 + if ((int) mbstrlen (buffer) > cols-2){
3796 buffer [cols] = 0;
3797 p += 2;
3798 } else
3799 @@ -1104,6 +1209,12 @@
3800 int side, width;
3802 const char *txt;
3803 +#ifdef UTF8
3804 + char buffer[30 * sizeof (wchar_t)];
3805 + mbstate_t s;
3807 + memset (&s, 0, sizeof (s));
3808 +#endif
3809 if (!panel->split)
3810 adjust_top_file (panel);
3812 @@ -1128,16 +1239,38 @@
3813 if (format->string_fn){
3814 txt = format->title;
3816 - header_len = strlen (txt);
3817 + attrset (MARKED_COLOR);
3818 + width -= format->field_len;
3819 +#ifdef UTF8
3820 + if (SLsmg_Is_Unicode) {
3821 + const char *str = txt;
3822 + header_len = mbsrtowcs ((wchar_t *) buffer, &str,
3823 + sizeof (buffer) / sizeof (wchar_t),
3824 + &s);
3825 + if (header_len < 0) {
3826 + memset (&s, 0, sizeof (s));
3827 + printw ("%*s", format->field_len, "");
3828 + continue;
3830 + if (header_len > format->field_len)
3831 + header_len = format->field_len;
3832 + spaces = (format->field_len - header_len) / 2;
3833 + extra = (format->field_len - header_len) % 2;
3834 + printw ("%*s", spaces, "");
3835 + SLsmg_write_nwchars ((wchar_t *) buffer, header_len);
3836 + printw ("%*s", spaces + extra, "");
3837 + continue;
3839 +#endif
3841 + header_len = mbstrlen (txt);
3842 if (header_len > format->field_len)
3843 header_len = format->field_len;
3845 - attrset (MARKED_COLOR);
3846 spaces = (format->field_len - header_len) / 2;
3847 extra = (format->field_len - header_len) % 2;
3848 tty_printf ("%*s%.*s%*s", spaces, "",
3849 header_len, txt, spaces+extra, "");
3850 - width -= 2 * spaces + extra + header_len;
3851 } else {
3852 attrset (NORMAL_COLOR);
3853 one_vline ();
3854 @@ -1894,11 +2027,24 @@
3855 int i;
3856 int wrapped = 0;
3857 int found;
3858 + int prevpos, pos;
3859 + int j;
3860 + mbstate_t mbs;
3862 l = strlen (panel->search_buffer);
3863 if (c_code == KEY_BACKSPACE) {
3864 - if (l)
3865 - panel->search_buffer[--l] = '\0';
3866 + if (l) {
3867 + prevpos = pos = 0;
3868 + memset (&mbs, 0, sizeof (mbs));
3869 + while (pos < l) {
3870 + prevpos = pos;
3871 + j = mbrlen (panel->search_buffer + pos, l - pos, &mbs);
3872 + if (j <= 0) break;
3873 + pos += j;
3875 + --l;
3876 + panel->search_buffer[prevpos] = 0;
3878 } else {
3879 if (c_code && l < sizeof (panel->search_buffer)) {
3880 panel->search_buffer[l] = c_code;
3881 @@ -1907,6 +2053,14 @@
3885 + prevpos = pos = 0;
3886 + memset (&mbs, 0, sizeof (mbs));
3887 + while (pos < l) {
3888 + prevpos = pos;
3889 + j = mbrlen (panel->search_buffer + pos, l - pos, &mbs);
3890 + if (j <= 0) break;
3891 + pos += j;
3893 found = 0;
3894 for (i = panel->selected; !wrapped || i != panel->selected; i++) {
3895 if (i >= panel->count) {
3896 @@ -1917,9 +2071,9 @@
3898 if (panel->
3899 case_sensitive
3900 - ? (strncmp (panel->dir.list[i].fname, panel->search_buffer, l)
3901 + ? (strncmp (panel->dir.list[i].fname, panel->search_buffer, pos)
3902 == 0) : (g_strncasecmp (panel->dir.list[i].fname,
3903 - panel->search_buffer, l) == 0)) {
3904 + panel->search_buffer, pos) == 0)) {
3905 unselect_item (panel);
3906 panel->selected = i;
3907 select_item (panel);
3908 @@ -1928,7 +2082,7 @@
3911 if (!found)
3912 - panel->search_buffer[--l] = 0;
3913 + panel->search_buffer[prevpos] = 0;
3915 paint_panel (panel);
3917 --- mc-4.6.2-pre1/src/slint.c
3918 +++ mc-4.6.2-pre1/src/slint.c
3919 @@ -141,7 +141,9 @@
3920 slang_init (void)
3922 SLtt_get_terminfo ();
3924 +#if SLANG_VERSION >= 20000
3925 + SLutf8_enable (-1);
3926 +#endif
3928 * If the terminal in not in terminfo but begins with a well-known
3929 * string such as "linux" or "xterm" S-Lang will go on, but the
3930 --- mc-4.6.2-pre1/src/tty.c
3931 +++ mc-4.6.2-pre1/src/tty.c
3932 @@ -134,10 +134,12 @@
3933 * defined or not. Congratulations! At least, they left the API call
3934 * for SLsmg_write_nchars as it has always been.
3936 - char ch;
3938 - ch = c;
3939 - SLsmg_write_nchars(&ch, 1);
3941 + /* The above comment is a nonsense, SLsmg_write_char(c) works pretty
3942 + * good for me. So please don't mess with Red Hat people.
3943 + * Jindrich Novy (jnovy@redhat.com)
3944 + */
3945 + SLsmg_write_char(c);
3946 #else
3947 addch(c);
3948 #endif
3949 --- mc-4.6.2-pre1/src/tty.h
3950 +++ mc-4.6.2-pre1/src/tty.h
3951 @@ -8,6 +8,8 @@
3952 of ifdefs in the other files small.
3955 +#include <glib.h> /* gboolean is used here */
3957 #ifdef HAVE_SLANG
3958 # include "myslang.h"
3959 #endif
3960 --- mc-4.6.2-pre1/src/util.c
3961 +++ mc-4.6.2-pre1/src/util.c
3962 @@ -33,7 +33,11 @@
3963 #include <sys/types.h>
3964 #include <sys/stat.h>
3965 #include <unistd.h>
3966 +#include <iconv.h>
3967 +#include <langinfo.h>
3968 +#include <errno.h>
3970 +#include "tty.h"
3971 #include "global.h"
3972 #include "profile.h"
3973 #include "main.h" /* mc_home */
3974 @@ -45,9 +49,39 @@
3975 #include "charsets.h"
3976 #endif
3978 +#ifdef UTF8
3979 +#include <wctype.h>
3980 +#endif
3982 static const char app_text [] = "Midnight-Commander";
3983 int easy_patterns = 1;
3985 +#if SLANG_VERSION >= 20000
3986 +void SLsmg_write_nwchars(wchar_t *s, size_t n)
3988 + if (SLsmg_is_utf8_mode()) { /* slang can handle it directly */
3989 + while(n-- && *s)
3990 + SLsmg_write_char(*s++);
3992 + else { /* convert wchars back to 8bit encoding */
3993 + mbstate_t mbs;
3994 + memset (&mbs, 0, sizeof (mbs));
3995 + while (n-- && *s) {
3996 + char buf[MB_LEN_MAX + 1]; /* should use 1 char, but to be sure */
3997 + if (*s < 0x80) {
3998 + SLsmg_write_char(*s++); /* ASCII */
4000 + else {
4001 + if (wcrtomb(buf, *s++, &mbs) == 1)
4002 + SLsmg_write_char((wchar_t)(buf[0]));
4003 + else
4004 + SLsmg_write_char('?'); /* should not happen */
4006 + }
4009 +#endif
4011 extern void str_replace(char *s, char from, char to)
4013 for (; *s != '\0'; s++) {
4014 @@ -78,9 +112,106 @@
4015 return (c > 31 && c != 127 && c != 155);
4018 +size_t
4019 +mbstrlen (const char *str)
4021 +#ifdef UTF8
4022 + if (SLsmg_Is_Unicode) {
4023 + size_t width = 0;
4025 + for (; *str; str++) {
4026 + wchar_t c;
4027 + size_t len;
4029 + len = mbrtowc (&c, str, MB_CUR_MAX, NULL);
4031 + if (len == (size_t)(-1) || len == (size_t)(-2)) break;
4033 + if (len > 0) {
4034 + int wcsize = wcwidth(c);
4035 + width += wcsize > 0 ? wcsize : 0;
4036 + str += len-1;
4040 + return width;
4041 + } else
4042 +#endif
4043 + return strlen (str);
4046 +#ifdef UTF8
4048 +void
4049 +fix_utf8(char *str)
4051 + mbstate_t mbs;
4053 + char *p = str;
4055 + while (*p) {
4056 + int len;
4057 + memset (&mbs, 0, sizeof (mbs));
4058 + len = mbrlen(p, MB_CUR_MAX, &mbs);
4059 + if (len == -1) {
4060 + *p = '?';
4061 + p++;
4062 + } else if (len > 0) {
4063 + p += len;
4064 + } else {
4065 + p++;
4069 +#endif
4073 +#ifdef UTF8
4074 +wchar_t *
4075 +mbstr_to_wchar (const char *str)
4077 + int len = mbstrlen(str);
4078 + wchar_t *buf = g_malloc((len+1) * sizeof(wchar_t));
4079 + mbstate_t mbs;
4080 + memset (&mbs, 0, sizeof (mbs));
4081 + mbsrtowcs (buf, &str, len, &mbs);
4082 + buf[len] = 0;
4083 + return buf;
4086 +char *
4087 +wchar_to_mbstr (const wchar_t *wstr)
4089 + mbstate_t mbs;
4090 + const wchar_t *wstr2;
4091 + char * string;
4092 + int len;
4094 + memset (&mbs, 0, sizeof (mbs));
4095 + wstr2 = wstr;
4096 + len = wcsrtombs(NULL, &wstr2, 0, &mbs);
4097 + if (len <= 0)
4098 + return NULL;
4100 + string = g_malloc(len + 1);
4102 + wstr2 = wstr;
4103 + wcsrtombs(string, &wstr2, len, &mbs);
4104 + string[len] = 0;
4105 + return string;
4107 +#endif
4112 is_printable (int c)
4114 +#ifdef UTF8
4115 + if (SLsmg_Is_Unicode)
4116 + return iswprint (c);
4117 +#endif
4118 c &= 0xff;
4120 #ifdef HAVE_CHARSET
4121 @@ -98,7 +229,7 @@
4122 #endif /* !HAVE_CHARSET */
4125 -/* Calculates the message dimensions (lines and columns) */
4126 +/* Calculates the message dimension in columns and lines. */
4127 void
4128 msglen (const char *text, int *lines, int *columns)
4130 @@ -111,8 +242,21 @@
4131 nlines++;
4132 colindex = 0;
4133 } else {
4134 +#ifndef UTF8
4135 colindex++;
4136 if (colindex > ncolumns)
4137 +#else /* UTF8 */
4138 + size_t len;
4139 + wchar_t c;
4141 + len = mbrtowc (&c, text, MB_CUR_MAX, NULL);
4142 + if (len > 0 && len != (size_t)(-1) && len != (size_t)(-2)) {
4143 + int wcsize = wcwidth(c);
4144 + colindex += wcsize > 0 ? wcsize-1 : -1;
4145 + text += len-1;
4147 + if (++colindex > ncolumns)
4148 +#endif /* UTF8 */
4149 ncolumns = colindex;
4152 @@ -206,7 +350,24 @@
4153 *d++ = '\\';
4154 break;
4156 +#ifndef UTF8
4157 *d = *s;
4158 +#else /* UTF8 */
4160 + mbstate_t mbs;
4161 + int len;
4162 + memset (&mbs, 0, sizeof (mbs));
4163 + len = mbrlen(s, MB_CUR_MAX, &mbs);
4164 + if (len > 0) {
4165 + while (len-- > 1)
4166 + *d++ = *s++;
4167 + *d = *s;
4168 + } else {
4169 + *d = '?';
4173 +#endif /* UTF8 */
4175 *d = '\0';
4176 return ret;
4177 @@ -228,25 +389,90 @@
4178 name_trunc (const char *txt, int trunc_len)
4180 static char x[MC_MAXPATHLEN + MC_MAXPATHLEN];
4181 - int txt_len;
4182 + int txt_len, first, skip;
4183 char *p;
4184 + const char *str;
4186 if ((size_t) trunc_len > sizeof (x) - 1) {
4187 trunc_len = sizeof (x) - 1;
4189 - txt_len = strlen (txt);
4190 - if (txt_len <= trunc_len) {
4191 - strcpy (x, txt);
4192 - } else {
4193 - int y = (trunc_len / 2) + (trunc_len % 2);
4194 - strncpy (x, txt, y);
4195 - strncpy (x + y, txt + txt_len - (trunc_len / 2), trunc_len / 2);
4196 - x[y] = '~';
4198 - x[trunc_len] = 0;
4199 - for (p = x; *p; p++)
4200 - if (!is_printable (*p))
4201 - *p = '?';
4202 + txt_len = mbstrlen (txt);
4203 + first = 0;
4204 + skip = 0;
4205 + if (txt_len > trunc_len) {
4206 + first = trunc_len / 2;
4207 + skip = txt_len - trunc_len + 1;
4210 +#ifdef UTF8
4211 + if (SLsmg_Is_Unicode) {
4212 + mbstate_t s;
4213 + int mbmax;
4215 + str = txt;
4216 + memset (&s, 0, sizeof (s));
4217 + mbmax = MB_CUR_MAX;
4218 + p = x;
4219 + while (p < x + sizeof (x) - 1 && trunc_len) {
4220 + wchar_t wc;
4221 + int len;
4223 + len = mbrtowc (&wc, str, mbmax, &s);
4224 + if (!len)
4225 + break;
4226 + if (len < 0) {
4227 + memset (&s, 0, sizeof (s));
4228 + *p = '?';
4229 + len = 1;
4230 + str++;
4231 + } else if (!is_printable (wc)) {
4232 + *p = '?';
4233 + str += len;
4234 + len = 1;
4235 + } else if (p >= x + sizeof (x) - len)
4236 + break;
4237 + else {
4238 + memcpy (p, str, len);
4239 + str += len;
4241 + if (first) {
4242 + --trunc_len;
4243 + --first;
4244 + p += len;
4245 + if (!first && p < x + sizeof (x) - 1 && trunc_len) {
4246 + *p++ = '~';
4247 + --trunc_len;
4249 + } else if (skip)
4250 + --skip;
4251 + else {
4252 + --trunc_len;
4253 + p += len;
4256 + } else
4257 +#endif
4259 + str = txt;
4260 + p = x;
4261 + while (p < x + sizeof (x) - 1) {
4262 + if (*str == '\0')
4263 + break;
4264 + else if (!is_printable (*str))
4265 + *p++ = '?';
4266 + else
4267 + *p++ = *str;
4268 + ++str;
4269 + if (first) {
4270 + --first;
4271 + if (!first) {
4272 + *p++ = '~';
4273 + str += skip;
4278 + *p = '\0';
4279 return x;
4282 @@ -678,11 +904,61 @@
4285 char *
4286 +utf8_to_local(char *str)
4288 + iconv_t cd;
4289 + size_t buflen = strlen(str);
4290 + char *output;
4291 + int retry = 1;
4293 + cd = iconv_open (nl_langinfo(CODESET), "UTF-8");
4294 + if (cd == (iconv_t) -1) {
4295 + return g_strdup(str);
4298 + output = g_malloc(buflen + 1);
4300 + while (retry)
4302 + char *wrptr = output;
4303 + char *inptr = str;
4304 + size_t insize = buflen;
4305 + size_t avail = buflen;
4306 + size_t nconv;
4308 + nconv = iconv (cd, &inptr, &insize, &wrptr, &avail);
4309 + if (nconv == (size_t) -1)
4311 + if (errno == E2BIG)
4313 + buflen *= 2;
4314 + g_free(output);
4315 + output = g_malloc(buflen + 1);
4317 + else
4319 + g_free(output);
4320 + return g_strdup(str);
4323 + else {
4324 + retry = 0;
4325 + *wrptr = 0;
4329 + iconv_close (cd);
4331 + return output;
4334 +char *
4335 load_mc_home_file (const char *filename, char **allocated_filename)
4337 char *hintfile_base, *hintfile;
4338 char *lang;
4339 char *data;
4340 + char *conv_data;
4342 hintfile_base = concat_dir_and_file (mc_home, filename);
4343 lang = guess_message_value ();
4344 @@ -715,7 +991,10 @@
4345 else
4346 g_free (hintfile);
4348 - return data;
4349 + conv_data = utf8_to_local(data);
4350 + g_free(data);
4352 + return conv_data;
4355 /* Check strftime() results. Some systems (i.e. Solaris) have different
4356 @@ -724,12 +1003,14 @@
4357 i18n_checktimelength (void)
4359 size_t length, a, b;
4360 - char buf [MAX_I18NTIMELENGTH + 1];
4361 + char buf [4 * MAX_I18NTIMELENGTH + 1];
4362 time_t testtime = time (NULL);
4364 - a = strftime (buf, sizeof(buf)-1, _("%b %e %H:%M"), localtime(&testtime));
4365 - b = strftime (buf, sizeof(buf)-1, _("%b %e %Y"), localtime(&testtime));
4367 + strftime (buf, sizeof(buf)-1, _("%b %e %H:%M"), localtime(&testtime));
4368 + a = mbstrlen (buf);
4369 + strftime (buf, sizeof(buf)-1, _("%b %e %Y"), localtime(&testtime));
4370 + b = mbstrlen (buf);
4372 length = max (a, b);
4374 /* Don't handle big differences. Use standard value (email bug, please) */
4375 @@ -742,15 +1023,12 @@
4376 const char *
4377 file_date (time_t when)
4379 - static char timebuf [MAX_I18NTIMELENGTH + 1];
4380 + static char timebuf [4 * MAX_I18NTIMELENGTH + 1];
4381 time_t current_time = time ((time_t) 0);
4382 - static size_t i18n_timelength = 0;
4383 static const char *fmtyear, *fmttime;
4384 const char *fmt;
4386 - if (i18n_timelength == 0){
4387 - i18n_timelength = i18n_checktimelength() + 1;
4389 + if (fmtyear == NULL) {
4390 /* strftime() format string for old dates */
4391 fmtyear = _("%b %e %Y");
4392 /* strftime() format string for recent dates */
4393 @@ -770,7 +1048,7 @@
4394 else
4395 fmt = fmttime;
4397 - strftime (timebuf, i18n_timelength, fmt, localtime(&when));
4398 + strftime (timebuf, sizeof (timebuf) - 1, fmt, localtime(&when));
4399 return timebuf;
4402 @@ -900,10 +1178,27 @@
4403 r++;
4404 continue;
4407 +#ifndef UTF8
4408 if (is_printable(*r))
4409 *w++ = *r;
4410 ++r;
4411 +#else /* UTF8 */
4413 + mbstate_t mbs;
4414 + int len;
4415 + memset (&mbs, 0, sizeof (mbs));
4416 + len = mbrlen(r, MB_CUR_MAX, &mbs);
4418 + if (len > 0 && (unsigned char)*r >= ' ')
4419 + while (len--)
4420 + *w++ = *r++;
4421 + else {
4422 + if (len == -1)
4423 + *w++ = '?';
4424 + r++;
4427 +#endif /* UTF8 */
4429 *w = 0;
4430 return s;
4431 --- mc-4.6.2-pre1/src/util.h
4432 +++ mc-4.6.2-pre1/src/util.h
4433 @@ -103,6 +103,13 @@
4434 char *get_group (int);
4435 char *get_owner (int);
4437 +void fix_utf8(char *str);
4438 +size_t mbstrlen (const char *);
4439 +wchar_t *mbstr_to_wchar (const char *);
4440 +char *wchar_to_mbstr (const wchar_t *);
4441 +char *utf8_to_local(char *str);
4444 #define MAX_I18NTIMELENGTH 14
4445 #define MIN_I18NTIMELENGTH 10
4446 #define STD_I18NTIMELENGTH 12
4447 --- mc-4.6.2-pre1/src/view.c
4448 +++ mc-4.6.2-pre1/src/view.c
4449 @@ -43,6 +43,10 @@
4450 #include <sys/stat.h>
4451 #include <unistd.h>
4453 +#ifdef UTF8
4454 +#include <wctype.h>
4455 +#endif /* UTF8 */
4457 #include "global.h"
4458 #include "tty.h"
4459 #include "cmd.h" /* For view_other_cmd */
4460 @@ -1642,7 +1646,7 @@
4461 hline (' ', width);
4463 file_label = _("File: %s");
4464 - file_label_width = strlen (file_label) - 2;
4465 + file_label_width = mbstrlen (file_label) - 2;
4466 file_name = view->filename ? view->filename
4467 : view->command ? view->command
4468 : "";
4469 @@ -1910,6 +1914,12 @@
4470 offset_type from;
4471 int c;
4472 struct hexedit_change_node *curr = view->change_list;
4473 +#ifdef UTF8
4474 + mbstate_t mbs;
4475 + char mbbuf[MB_LEN_MAX];
4476 + int mblen;
4477 + wchar_t wc;
4478 +#endif /* UTF8 */
4480 view_display_clean (view);
4481 view_display_ruler (view);
4482 @@ -1922,8 +1932,37 @@
4484 tty_setcolor (NORMAL_COLOR);
4485 for (row = 0, col = 0; row < height && (c = get_byte (view, from)) != -1; from++) {
4487 +#ifndef UTF8
4488 if (view->text_nroff_mode && c == '\b') {
4489 +#else /* UTF8 */
4490 + mblen = 1;
4491 + mbbuf[0] = convert_to_display_c (c);
4493 + while (mblen < MB_LEN_MAX) {
4494 + int res;
4495 + memset (&mbs, 0, sizeof (mbs));
4496 + res = mbrtowc (&wc, mbbuf, mblen, &mbs);
4497 + if (res <= 0 && res != -2) {
4498 + wc = '.';
4499 + mblen = 1;
4500 + break;
4502 + if (res == mblen)
4503 + break;
4505 + mbbuf[mblen] = convert_to_display_c (get_byte (view, from + mblen));
4506 + mblen++;
4509 + if (mblen == MB_LEN_MAX) {
4510 + wc = '.';
4511 + mblen = 1;
4514 + from += mblen - 1;
4516 + if (view->text_nroff_mode && wc == '\b') {
4517 +#endif /* UTF8 */
4518 int c_prev;
4519 int c_next;
4521 @@ -1988,10 +2027,17 @@
4522 if (col >= view->dpy_text_column
4523 && col - view->dpy_text_column < width) {
4524 widget_move (view, top + row, left + (col - view->dpy_text_column));
4525 +#ifndef UTF8
4526 c = convert_to_display_c (c);
4527 if (!is_printable (c))
4528 c = '.';
4529 tty_print_char (c);
4530 +#else
4531 + wc = convert_to_display_c (wc);
4532 + if (!iswprint (wc))
4533 + wc = '.';
4534 + tty_print_char (wc);
4535 +#endif
4537 col++;
4538 tty_setcolor (NORMAL_COLOR);
4539 --- mc-4.6.2-pre1/src/widget.c
4540 +++ mc-4.6.2-pre1/src/widget.c
4541 @@ -36,6 +36,9 @@
4543 #include "global.h"
4544 #include "tty.h"
4545 +#ifdef UTF8
4546 +#include <wctype.h>
4547 +#endif /* UTF8 */
4548 #include "color.h"
4549 #include "mouse.h"
4550 #include "dialog.h"
4551 @@ -182,6 +185,11 @@
4552 if (b->hotpos >= 0) {
4553 widget_selectcolor (w, b->selected, TRUE);
4554 widget_move (w, 0, b->hotpos + off);
4555 +#ifdef UTF8
4556 + if (SLsmg_Is_Unicode)
4557 + SLsmg_write_nwchars (&b->hotwc, 1);
4558 + else
4559 +#endif
4560 addch ((unsigned char) b->text[b->hotpos]);
4562 return MSG_HANDLED;
4563 @@ -215,7 +223,7 @@
4564 static int
4565 button_len (const char *text, unsigned int flags)
4567 - int ret = strlen (text);
4568 + int ret = mbstrlen (text);
4569 switch (flags){
4570 case DEFPUSH_BUTTON:
4571 ret += 6;
4572 @@ -238,14 +246,36 @@
4573 * the button text is g_malloc()ed, we can safely change and shorten it.
4575 static void
4576 -button_scan_hotkey (WButton *b)
4577 +scan_hotkey (char *text, int *hotposp, int *hotkeyp, wchar_t *hotwcp)
4579 - char *cp = strchr (b->text, '&');
4580 + char *cp = strchr (text, '&');
4582 if (cp != NULL && cp[1] != '\0') {
4583 - g_strlcpy (cp, cp + 1, strlen (cp));
4584 - b->hotkey = tolower ((unsigned char) *cp);
4585 - b->hotpos = cp - b->text;
4586 +#ifdef UTF8
4587 + if (SLsmg_Is_Unicode) {
4588 + mbstate_t s;
4589 + int len;
4591 + *cp = '\0';
4592 + memset (&s, 0, sizeof (s));
4593 + len = mbrtowc (hotwcp, cp + 1, MB_CUR_MAX, &s);
4594 + if (len > 0) {
4595 + *hotposp = mbstrlen (text);
4596 + if (*hotposp < 0) {
4597 + *hotposp = -1;
4598 + } else {
4599 + /* FIXME */
4600 + *hotkeyp = tolower (*hotwcp);
4603 + } else
4604 +#endif
4606 + *hotkeyp = tolower (cp[1]);
4607 + *hotposp = cp - text;
4610 + memmove (cp, cp + 1, strlen (cp + 1) + 1);
4614 @@ -266,8 +296,9 @@
4615 widget_want_hotkey (b->widget, 1);
4616 b->hotkey = 0;
4617 b->hotpos = -1;
4618 + b->hotwc = L'\0';
4620 - button_scan_hotkey(b);
4621 + scan_hotkey(b->text, &b->hotpos, &b->hotkey, &b->hotwc);
4622 return b;
4625 @@ -280,14 +311,13 @@
4626 void
4627 button_set_text (WButton *b, const char *text)
4629 - g_free (b->text);
4630 + g_free (b->text);
4631 b->text = g_strdup (text);
4632 b->widget.cols = button_len (text, b->flags);
4633 - button_scan_hotkey(b);
4634 + scan_hotkey(b->text, &b->hotpos, &b->hotkey, &b->hotwc);
4635 dlg_redraw (b->widget.parent);
4639 /* Radio button widget */
4640 static int radio_event (Gpm_Event *event, void *);
4642 @@ -362,14 +392,35 @@
4643 widget_move (&r->widget, i, 0);
4645 tty_printf ("(%c) ", (r->sel == i) ? '*' : ' ');
4646 - for (cp = r->texts[i]; *cp; cp++) {
4647 - if (*cp == '&') {
4648 - widget_selectcolor (w, focused, TRUE);
4649 + cp = strchr (r->texts[i], '&');
4650 + if (cp != NULL) {
4651 +#ifdef UTF8
4652 + mbstate_t s;
4653 + wchar_t wc;
4654 + int len;
4655 +#endif
4656 + tty_printf ("%.*s", (int) ((char *) cp - r->texts[i]),
4657 + r->texts[i]);
4658 + widget_selectcolor (w, focused, TRUE);
4659 +#ifdef UTF8
4660 + if (SLsmg_Is_Unicode) {
4661 + memset (&s, 0, sizeof (s));
4662 + len = mbrtowc (&wc, cp + 1, MB_CUR_MAX, &s);
4663 + ++cp;
4664 + if (len > 0) {
4665 + tty_printf ("%.*s", len, cp);
4666 + cp += len;
4668 + } else
4669 +#endif
4671 addch (*++cp);
4672 - widget_selectcolor (w, focused, FALSE);
4673 - } else
4674 - addch (*cp);
4676 + ++cp;
4678 + widget_selectcolor (w, focused, FALSE);
4679 + } else
4680 + cp = r->texts[i];
4681 + addstr ((char *) cp);
4683 return MSG_HANDLED;
4685 @@ -408,7 +459,7 @@
4686 /* Compute the longest string */
4687 max = 0;
4688 for (i = 0; i < count; i++){
4689 - m = strlen (texts [i]);
4690 + m = mbstrlen (texts [i]);
4691 if (m > max)
4692 max = m;
4694 @@ -468,6 +519,11 @@
4695 if (c->hotpos >= 0) {
4696 widget_selectcolor (w, msg == WIDGET_FOCUS, TRUE);
4697 widget_move (&c->widget, 0, +c->hotpos + 4);
4698 +#ifdef UTF8
4699 + if (SLsmg_Is_Unicode)
4700 + SLsmg_write_nwchars (&c->hotwc, 1);
4701 + else
4702 +#endif
4703 addch ((unsigned char) c->text[c->hotpos]);
4705 return MSG_HANDLED;
4706 @@ -505,35 +561,20 @@
4707 check_new (int y, int x, int state, const char *text)
4709 WCheck *c = g_new (WCheck, 1);
4710 - const char *s;
4711 - char *t;
4713 - init_widget (&c->widget, y, x, 1, strlen (text),
4715 + init_widget (&c->widget, y, x, 1, mbstrlen (text),
4716 check_callback, check_event);
4717 c->state = state ? C_BOOL : 0;
4718 c->text = g_strdup (text);
4719 c->hotkey = 0;
4720 c->hotpos = -1;
4721 + c->hotwc = L'\0';
4722 widget_want_hotkey (c->widget, 1);
4724 - /* Scan for the hotkey */
4725 - for (s = text, t = c->text; *s; s++, t++){
4726 - if (*s != '&'){
4727 - *t = *s;
4728 - continue;
4730 - s++;
4731 - if (*s){
4732 - c->hotkey = tolower ((unsigned char) *s);
4733 - c->hotpos = t - c->text;
4735 - *t = *s;
4737 - *t = 0;
4738 + scan_hotkey (c->text, &c->hotpos, &c->hotkey, &c->hotwc);
4739 return c;
4743 /* Label widget */
4745 static cb_ret_t
4746 @@ -572,7 +613,7 @@
4748 widget_move (&l->widget, y, 0);
4749 tty_printf ("%s", p);
4750 - xlen = l->widget.cols - strlen (p);
4751 + xlen = l->widget.cols - mbstrlen (p);
4752 if (xlen > 0)
4753 tty_printf ("%*s", xlen, " ");
4754 if (!q)
4755 @@ -606,7 +647,7 @@
4756 if (text){
4757 label->text = g_strdup (text);
4758 if (label->auto_adjust_cols) {
4759 - newcols = strlen (text);
4760 + newcols = mbstrlen (text);
4761 if (newcols > label->widget.cols)
4762 label->widget.cols = newcols;
4764 @@ -630,7 +671,7 @@
4765 if (!text || strchr(text, '\n'))
4766 width = 1;
4767 else
4768 - width = strlen (text);
4769 + width = mbstrlen (text);
4771 l = g_new (WLabel, 1);
4772 init_widget (&l->widget, y, x, 1, width, label_callback, NULL);
4773 @@ -778,13 +819,69 @@
4774 /* Pointer to killed data */
4775 static char *kill_buffer = 0;
4777 +#ifdef UTF8
4778 +static int
4779 +charpos(WInput *in, int idx)
4781 + int i, pos, l, len;
4782 + mbstate_t mbs;
4783 + memset (&mbs, 0, sizeof (mbs));
4784 + i = 0;
4785 + pos = 0;
4786 + len = strlen(in->buffer);
4788 + while (in->buffer[pos]) {
4789 + if (i == idx)
4790 + return pos;
4791 + l = mbrlen(in->buffer + pos, len - pos, &mbs);
4792 + if (l <= 0)
4793 + return pos;
4794 + pos+=l;
4795 + i++;
4796 + };
4797 + return pos;
4800 +static int
4801 +charcolumn(WInput *in, int idx)
4803 + int i, pos, l, width, len;
4804 + mbstate_t mbs;
4805 + memset (&mbs, 0, sizeof (mbs));
4806 + i = 0;
4807 + pos = 0; width = 0;
4808 + len = strlen(in->buffer);
4810 + while (in->buffer[pos]) {
4811 + wchar_t wc;
4812 + if (i == idx)
4813 + return width;
4814 + l = mbrtowc(&wc, in->buffer + pos, len - pos, &mbs);
4815 + if (l <= 0)
4816 + return width;
4817 + pos += l; width += wcwidth(wc);
4818 + i++;
4819 + };
4820 + return width;
4822 +#else
4823 +#define charpos(in, idx) (idx)
4824 +#define charcolumn(in, idx) (idx)
4825 +#endif /* UTF8 */
4827 void
4828 update_input (WInput *in, int clear_first)
4830 int has_history = 0;
4831 int i, j;
4832 - unsigned char c;
4833 - int buf_len = strlen (in->buffer);
4834 + int buf_len = mbstrlen (in->buffer);
4835 +#ifndef UTF8
4836 + unsigned char c;
4837 +#else /* UTF8 */
4838 + wchar_t c;
4839 + mbstate_t mbs;
4840 + memset (&mbs, 0, sizeof (mbs));
4841 +#endif /* UTF8 */
4843 if (should_show_history_button (in))
4844 has_history = HISTORY_BUTTON_WIDTH;
4845 @@ -794,7 +891,7 @@
4847 /* Make the point visible */
4848 if ((in->point < in->first_shown) ||
4849 - (in->point >= in->first_shown+in->field_len - has_history)){
4850 + (charcolumn(in, in->point) >= charcolumn(in, in->first_shown) + in->field_len - has_history)){
4851 in->first_shown = in->point - (in->field_len / 3);
4852 if (in->first_shown < 0)
4853 in->first_shown = 0;
4854 @@ -814,14 +911,29 @@
4855 addch (' ');
4856 widget_move (&in->widget, 0, 0);
4858 +#ifndef UTF8
4859 for (i = 0, j = in->first_shown; i < in->field_len - has_history && in->buffer [j]; i++){
4860 c = in->buffer [j++];
4861 c = is_printable (c) ? c : '.';
4862 - if (in->is_password)
4863 +#else /* UTF8 */
4864 + for (i = 0, j = in->first_shown; (i < in->field_len - has_history) && (j < buf_len); i++,j++){
4865 + char * chp = in->buffer + charpos(in,j);
4866 + size_t res = mbrtowc(&c, chp, strlen(chp), &mbs);
4867 + c = (res && iswprint (c)) ? 0 : '.';
4868 +#endif /* UTF8 */
4869 + if (in->is_password)
4870 c = '*';
4871 +#ifndef UTF8
4872 addch (c);
4873 +#else /* UTF8 */
4874 + if (c) {
4875 + addch (c);
4877 + else
4878 + SLsmg_write_nchars (chp, res);
4879 +#endif /* UTF8 */
4881 - widget_move (&in->widget, 0, in->point - in->first_shown);
4882 + widget_move (&in->widget, 0, charcolumn(in, in->point) - charcolumn(in, in->first_shown));
4884 if (clear_first)
4885 in->first = 0;
4886 @@ -974,7 +1086,7 @@
4887 show_hist (GList *history, int widget_x, int widget_y)
4889 GList *hi, *z;
4890 - size_t maxlen = strlen (i18n_htitle ()), i, count = 0;
4891 + size_t maxlen = mbstrlen (i18n_htitle ()), i, count = 0;
4892 int x, y, w, h;
4893 char *q, *r = 0;
4894 Dlg_head *query_dlg;
4895 @@ -987,7 +1099,7 @@
4896 z = g_list_first (history);
4897 hi = z;
4898 while (hi) {
4899 - if ((i = strlen ((char *) hi->data)) > maxlen)
4900 + if ((i = mbstrlen ((char *) hi->data)) > maxlen)
4901 maxlen = i;
4902 count++;
4903 hi = g_list_next (hi);
4904 @@ -1157,35 +1269,83 @@
4905 in->need_push = 1;
4906 in->buffer [0] = 0;
4907 in->point = 0;
4908 + in->charpoint = 0;
4909 in->mark = 0;
4910 free_completions (in);
4911 update_input (in, 0);
4914 +static void
4915 +move_buffer_backward (WInput *in, int point)
4917 + int i, pos, len;
4918 + int str_len = mbstrlen (in->buffer);
4919 + if (point >= str_len) return;
4921 + pos = charpos(in,point);
4922 + len = charpos(in,point + 1) - pos;
4924 + for (i = pos; in->buffer [i + len - 1]; i++)
4925 + in->buffer [i] = in->buffer [i + len];
4928 static cb_ret_t
4929 insert_char (WInput *in, int c_code)
4931 size_t i;
4932 +#ifdef UTF8
4933 + mbstate_t mbs;
4934 + int res;
4936 + memset (&mbs, 0, sizeof (mbs));
4937 +#else
4938 + in->charpoint = 0;
4939 +#endif /* UTF8 */
4941 if (c_code == -1)
4942 return MSG_NOT_HANDLED;
4944 +#ifdef UTF8
4945 + if (in->charpoint >= MB_CUR_MAX) return 1;
4947 + in->charbuf[in->charpoint++] = c_code;
4949 + res = mbrlen((char *)in->charbuf, in->charpoint, &mbs);
4950 + if (res < 0) {
4951 + if (res != -2) in->charpoint = 0; /* broken multibyte char, skip */
4952 + return 1;
4955 +#endif /* UTF8 */
4956 in->need_push = 1;
4957 - if (strlen (in->buffer)+1 == (size_t) in->current_max_len){
4958 + if (strlen (in->buffer) + 1 + in->charpoint >= (size_t) in->current_max_len){
4959 /* Expand the buffer */
4960 - char *narea = g_realloc (in->buffer, in->current_max_len + in->field_len);
4961 + char *narea = g_realloc (in->buffer, in->current_max_len + in->field_len + in->charpoint);
4962 if (narea){
4963 in->buffer = narea;
4964 - in->current_max_len += in->field_len;
4965 + in->current_max_len += in->field_len + in->charpoint;
4968 +#ifndef UTF8
4969 if (strlen (in->buffer)+1 < (size_t) in->current_max_len){
4970 size_t l = strlen (&in->buffer [in->point]);
4971 for (i = l+1; i > 0; i--)
4972 in->buffer [in->point+i] = in->buffer [in->point+i-1];
4973 in->buffer [in->point] = c_code;
4974 +#else /* UTF8 */
4975 + if (strlen (in->buffer) + in->charpoint < in->current_max_len){
4976 + size_t ins_point = charpos(in,in->point); /* bytes from begin */
4977 + /* move chars */
4978 + size_t rest_bytes = strlen (in->buffer + ins_point);
4980 + for (i = rest_bytes + 1; i > 0; i--)
4981 + in->buffer [ins_point + i + in->charpoint - 1] = in->buffer [ins_point + i - 1];
4983 + memcpy(in->buffer + ins_point, in->charbuf, in->charpoint);
4984 +#endif /* UTF8 */
4985 in->point++;
4987 + in->charpoint = 0;
4988 return MSG_HANDLED;
4991 @@ -1193,12 +1353,14 @@
4992 beginning_of_line (WInput *in)
4994 in->point = 0;
4995 + in->charpoint = 0;
4998 static void
4999 end_of_line (WInput *in)
5001 - in->point = strlen (in->buffer);
5002 + in->point = mbstrlen (in->buffer);
5003 + in->charpoint = 0;
5006 static void
5007 @@ -1206,18 +1368,21 @@
5009 if (in->point)
5010 in->point--;
5011 + in->charpoint = 0;
5014 static void
5015 forward_char (WInput *in)
5017 - if (in->buffer [in->point])
5018 + if (in->buffer [charpos(in,in->point)])
5019 in->point++;
5020 + in->charpoint = 0;
5023 static void
5024 forward_word (WInput * in)
5026 +#ifndef UTF8
5027 char *p = in->buffer + in->point;
5029 while (*p
5030 @@ -1227,11 +1392,39 @@
5031 while (*p && isalnum ((unsigned char) *p))
5032 p++;
5033 in->point = p - in->buffer;
5034 +#else /* UTF8 */
5035 + mbstate_t mbs;
5036 + int len = mbstrlen (in->buffer);
5037 + memset (&mbs, 0, sizeof (mbs));
5039 + while (in->point < len) {
5040 + wchar_t c;
5041 + char *p = in->buffer + charpos(in,in->point);
5042 + size_t res = mbrtowc(&c, p, strlen(p), &mbs);
5043 + if (res <= 0 || !(iswspace (c) || iswpunct (c)))
5044 + break;
5045 + in->point++;
5048 + memset (&mbs, 0, sizeof (mbs));
5050 + while (in->point < len) {
5051 + wchar_t c;
5052 + char *p = in->buffer + charpos(in,in->point);
5053 + size_t res = mbrtowc(&c, p, strlen(p), &mbs);
5054 + if (res <= 0 || !iswalnum (c))
5055 + break;
5056 + in->point++;
5059 + in->charpoint = 0;
5060 +#endif /* UTF8 */
5063 static void
5064 backward_word (WInput *in)
5066 +#ifndef UTF8
5067 char *p = in->buffer + in->point;
5069 while (p - 1 > in->buffer - 1 && (isspace ((unsigned char) *(p - 1))
5070 @@ -1241,6 +1434,32 @@
5071 while (p - 1 > in->buffer - 1 && isalnum ((unsigned char) *(p - 1)))
5072 p--;
5073 in->point = p - in->buffer;
5074 +#else /* UTF8 */
5075 + mbstate_t mbs;
5077 + memset (&mbs, 0, sizeof (mbs));
5078 + while (in->point > 0) {
5079 + wchar_t c;
5080 + char *p = in->buffer + charpos(in,in->point);
5081 + size_t res = mbrtowc(&c, p, strlen(p), &mbs);
5082 + if (*p && (res <= 0 || !(iswspace (c) || iswpunct (c))))
5083 + break;
5084 + in->point--;
5087 + memset (&mbs, 0, sizeof (mbs));
5089 + while (in->point > 0) {
5090 + wchar_t c;
5091 + char *p = in->buffer + charpos(in,in->point);
5092 + size_t res = mbrtowc(&c, p, strlen(p), &mbs);
5093 + if (*p && (res <= 0 || !iswalnum (c)))
5094 + break;
5095 + in->point--;
5098 + in->charpoint = 0;
5099 +#endif /* UTF8 */
5102 static void
5103 @@ -1273,8 +1492,9 @@
5105 if (!in->point)
5106 return;
5107 - for (i = in->point; in->buffer [i-1]; i++)
5108 - in->buffer [i-1] = in->buffer [i];
5110 + move_buffer_backward(in, in->point - 1);
5111 + in->charpoint = 0;
5112 in->need_push = 1;
5113 in->point--;
5115 @@ -1282,10 +1502,8 @@
5116 static void
5117 delete_char (WInput *in)
5119 - int i;
5121 - for (i = in->point; in->buffer [i]; i++)
5122 - in->buffer [i] = in->buffer [i+1];
5123 + move_buffer_backward(in, in->point);
5124 + in->charpoint = 0;
5125 in->need_push = 1;
5128 @@ -1300,6 +1518,9 @@
5130 g_free (kill_buffer);
5132 + first=charpos(in,first);
5133 + last=charpos(in,last);
5135 kill_buffer = g_strndup(in->buffer+first,last-first);
5138 @@ -1308,11 +1529,13 @@
5140 int first = min (x_first, x_last);
5141 int last = max (x_first, x_last);
5142 - size_t len = strlen (&in->buffer [last]) + 1;
5143 + size_t len;
5145 in->point = first;
5146 in->mark = first;
5147 - memmove (&in->buffer [first], &in->buffer [last], len);
5148 + len = strlen (&in->buffer [charpos(in,last)]) + 1;
5149 + memmove (&in->buffer [charpos(in,first)], &in->buffer [charpos(in,last)], len);
5150 + in->charpoint = 0;
5151 in->need_push = 1;
5154 @@ -1329,6 +1552,8 @@
5155 copy_region (in, old_point, new_point);
5156 delete_region (in, old_point, new_point);
5157 in->need_push = 1;
5158 + in->charpoint = 0;
5159 + in->charpoint = 0;
5162 static void
5163 @@ -1372,16 +1597,20 @@
5165 if (!kill_buffer)
5166 return;
5167 + in->charpoint = 0;
5168 for (p = kill_buffer; *p; p++)
5169 insert_char (in, *p);
5170 + in->charpoint = 0;
5173 static void
5174 kill_line (WInput *in)
5176 + int chp = charpos(in,in->point);
5177 g_free (kill_buffer);
5178 - kill_buffer = g_strdup (&in->buffer [in->point]);
5179 - in->buffer [in->point] = 0;
5180 + kill_buffer = g_strdup (&in->buffer [chp]);
5181 + in->buffer [chp] = 0;
5182 + in->charpoint = 0;
5185 void
5186 @@ -1391,9 +1620,10 @@
5187 g_free (in->buffer);
5188 in->buffer = g_strdup (text); /* was in->buffer->text */
5189 in->current_max_len = strlen (in->buffer) + 1;
5190 - in->point = strlen (in->buffer);
5191 + in->point = mbstrlen (in->buffer);
5192 in->mark = 0;
5193 in->need_push = 1;
5194 + in->charpoint = 0;
5197 static void
5198 @@ -1520,6 +1750,7 @@
5199 *in->buffer = 0;
5200 in->point = 0;
5201 in->first = 0;
5202 + in->charpoint = 0;
5205 cb_ret_t
5206 @@ -1548,7 +1779,11 @@
5209 if (!input_map [i].fn){
5210 +#ifndef UTF8
5211 if (c_code > 255 || !is_printable (c_code))
5212 +#else /* UTF8 */
5213 + if (c_code > 255)
5214 +#endif /* UTF8 */
5215 return MSG_NOT_HANDLED;
5216 if (in->first){
5217 port_region_marked_for_delete (in);
5218 @@ -1581,6 +1816,9 @@
5219 if (pos != in->point)
5220 free_completions (in);
5221 in->point = pos;
5222 +#ifdef UTF8
5223 + in->charpoint = 0;
5224 +#endif /* UTF8 */
5225 update_input (in, 1);
5228 @@ -1621,7 +1859,7 @@
5229 return MSG_HANDLED;
5231 case WIDGET_CURSOR:
5232 - widget_move (&in->widget, 0, in->point - in->first_shown);
5233 + widget_move (&in->widget, 0, charcolumn(in, in->point) - charcolumn(in, in->first_shown));
5234 return MSG_HANDLED;
5236 case WIDGET_DESTROY:
5237 @@ -1645,7 +1883,7 @@
5238 && should_show_history_button (in)) {
5239 do_show_hist (in);
5240 } else {
5241 - in->point = strlen (in->buffer);
5242 + in->point = mbstrlen (in->buffer);
5243 if (event->x - in->first_shown - 1 < in->point)
5244 in->point = event->x - in->first_shown - 1;
5245 if (in->point < 0)
5246 @@ -1702,7 +1940,8 @@
5247 in->is_password = 0;
5249 strcpy (in->buffer, def_text);
5250 - in->point = strlen (in->buffer);
5251 + in->point = mbstrlen (in->buffer);
5252 + in->charpoint = 0;
5253 return in;
5256 --- mc-4.6.2-pre1/src/widget.h
5257 +++ mc-4.6.2-pre1/src/widget.h
5258 @@ -22,6 +22,7 @@
5259 char *text; /* text of button */
5260 int hotkey; /* hot KEY */
5261 int hotpos; /* offset hot KEY char in text */
5262 + wchar_t hotwc;
5263 bcback callback; /* Callback function */
5264 } WButton;
5266 @@ -42,6 +43,7 @@
5267 char *text; /* text of check button */
5268 int hotkey; /* hot KEY */
5269 int hotpos; /* offset hot KEY char in text */
5270 + wchar_t hotwc;
5271 } WCheck;
5273 typedef struct WGauge {
5274 @@ -57,16 +59,20 @@
5276 typedef struct {
5277 Widget widget;
5278 - int point; /* cursor position in the input line */
5279 - int mark; /* The mark position */
5280 - int first_shown; /* Index of the first shown character */
5281 - int current_max_len; /* Maximum length of input line */
5282 - int field_len; /* Length of the editing field */
5283 + int point; /* cursor position in the input line (mb chars) */
5284 + int mark; /* The mark position (mb chars) */
5285 + int first_shown; /* Index of the first shown character (mb chars) */
5286 + int current_max_len; /* Maximum length of input line (bytes) */
5287 + int field_len; /* Length of the editing field (mb chars) */
5288 int color; /* color used */
5289 int first; /* Is first keystroke? */
5290 int disable_update; /* Do we want to skip updates? */
5291 int is_password; /* Is this a password input line? */
5292 char *buffer; /* pointer to editing buffer */
5293 +#ifdef UTF8
5294 + char charbuf[MB_LEN_MAX];
5295 +#endif /* UTF8 */
5296 + int charpoint;
5297 GList *history; /* The history */
5298 int need_push; /* need to push the current Input on hist? */
5299 char **completions; /* Possible completions array */
5300 --- mc-4.6.2-pre1/src/wtools.c
5301 +++ mc-4.6.2-pre1/src/wtools.c
5302 @@ -49,11 +49,11 @@
5303 /* Adjust sizes */
5304 lines = (lines > LINES - 6) ? LINES - 6 : lines;
5306 - if (title && (cols < (len = strlen (title) + 2)))
5307 + if (title && (cols < (len = mbstrlen (title) + 2)))
5308 cols = len;
5310 /* no &, but 4 spaces around button for brackets and such */
5311 - if (cols < (len = strlen (cancel_string) + 3))
5312 + if (cols < (len = mbstrlen (cancel_string) + 3))
5313 cols = len;
5315 cols = cols > COLS - 6 ? COLS - 6 : cols;
5316 @@ -124,7 +124,7 @@
5317 va_start (ap, count);
5318 for (i = 0; i < count; i++) {
5319 char *cp = va_arg (ap, char *);
5320 - win_len += strlen (cp) + 6;
5321 + win_len += mbstrlen (cp) + 6;
5322 if (strchr (cp, '&') != NULL)
5323 win_len--;
5325 @@ -133,7 +133,7 @@
5327 /* count coordinates */
5328 msglen (text, &lines, &cols);
5329 - cols = 6 + max (win_len, max ((int) strlen (header), cols));
5330 + cols = 6 + max (win_len, max ((int) mbstrlen (header), cols));
5331 lines += 4 + (count > 0 ? 2 : 0);
5332 xpos = COLS / 2 - cols / 2;
5333 ypos = LINES / 3 - (lines - 3) / 2;
5334 @@ -148,7 +148,7 @@
5335 va_start (ap, count);
5336 for (i = 0; i < count; i++) {
5337 cur_name = va_arg (ap, char *);
5338 - xpos = strlen (cur_name) + 6;
5339 + xpos = mbstrlen (cur_name) + 6;
5340 if (strchr (cur_name, '&') != NULL)
5341 xpos--;
5343 @@ -463,7 +463,7 @@
5344 quick_widgets[2].histname = histname;
5346 msglen (text, &lines, &cols);
5347 - len = max ((int) strlen (header), cols) + 4;
5348 + len = max ((int) mbstrlen (header), cols) + 4;
5349 len = max (len, 64);
5351 /* The special value of def_text is used to identify password boxes
5352 @@ -485,7 +485,7 @@
5353 quick_widgets[1].text = _(quick_widgets[1].text);
5354 quick_widgets[0].relative_x = len / 2 + 4;
5355 quick_widgets[1].relative_x =
5356 - len / 2 - (strlen (quick_widgets[1].text) + 9);
5357 + len / 2 - (mbstrlen (quick_widgets[1].text) + 9);
5358 quick_widgets[0].x_divisions = quick_widgets[1].x_divisions = len;
5359 #endif /* ENABLE_NLS */