4 From: Bram Moolenaar <Bram@moolenaar.net>
6 Content-Type: text/plain; charset=ISO-8859-1
7 Content-Transfer-Encoding: 8bit
11 Problem: Multi-byte characters cannot be used as hotkeys in a console
12 dialog. (Mattias Erkisson)
13 Solution: Handle multi-byte characters properly. Also put () or [] around
15 Files: src/message.c, src/macros.h
18 *** ../vim-6.2.205/src/message.c Thu Jan 8 20:54:45 2004
19 --- src/message.c Thu Jan 22 14:35:02 2004
29 /* Don't output anything in silent mode ("ex -s") */
35 ! case Ctrl_C: /* User aborts/cancels */
39 default: /* Could be a hotkey? */
40 ! if (c > 255) /* special keys are ignored here */
42 ! for (retval = 0; hotkeys[retval]; retval++)
44 ! if (hotkeys[retval] == TOLOWER_LOC(c))
47 ! if (hotkeys[retval])
52 /* No hotkey match, so keep waiting */
59 ! case Ctrl_C: /* User aborts/cancels */
63 default: /* Could be a hotkey? */
64 ! if (c < 0) /* special keys are ignored here */
66 ! /* Make the character lowercase, as chars in "hotkeys" are. */
69 ! for (i = 0; hotkeys[i]; ++i)
74 ! if ((*mb_ptr2char)(hotkeys + i) == c)
76 ! i += (*mb_ptr2len_check)(hotkeys + i) - 1;
80 ! if (hotkeys[i] == c)
86 /* No hotkey match, so keep waiting */
95 * Format the dialog string, and display it at the bottom of
96 * the screen. Return a string of hotkey chars (if defined) for
97 ! * each 'button'. If a button has no hotkey defined, the string
98 ! * has the buttons first letter.
100 ! * Returns allocated array, or NULL for error.
104 msg_show_console_dialog(message, buttons, dfltbutton)
109 + static int copy_char __ARGS((char_u *from, char_u *to, int lowercase));
112 + * Copy one character from "*from" to "*to", taking care of multi-byte
113 + * characters. Return the length of the character in bytes.
116 + copy_char(from, to, lowercase)
119 + int lowercase; /* make character lower case */
129 + c = MB_TOLOWER((*mb_ptr2char)(from));
130 + return (*mb_char2bytes)(c, to);
134 + len = (*mb_ptr2len_check)(from);
135 + mch_memmove(to, from, (size_t)len);
143 + *to = (char_u)TOLOWER_LOC(*from);
151 * Format the dialog string, and display it at the bottom of
152 * the screen. Return a string of hotkey chars (if defined) for
153 ! * each 'button'. If a button has no hotkey defined, the first character of
154 ! * the button is used.
155 ! * The hotkeys can be multi-byte characters, but without combining chars.
157 + * Returns an allocated string with hotkeys, or NULL for error.
160 msg_show_console_dialog(message, buttons, dfltbutton)
166 ! int lenhotkey = 1; /*first button*/
173 ! * First compute how long a string we need to allocate for the message.
178 ! if (*r == DLG_BUTTON_SEP)
180 ! len++; /* '\n' -> ', ' */
181 ! lenhotkey++; /* each button needs a hotkey */
183 ! else if (*r == DLG_HOTKEY_CHAR)
185 ! len++; /* '&a' -> '[a]' */
190 ! len += STRLEN(message)
191 ! + 2 /* for the NL's */
193 ! + 3; /* for the ": " and NUL */
195 ! lenhotkey++; /* for the NUL */
198 ! * Now allocate and load the strings
200 ! vim_free(confirm_msg);
201 ! confirm_msg = alloc(len);
202 ! if (confirm_msg == NULL)
204 ! *confirm_msg = NUL;
205 ! hotk = alloc(lenhotkey);
209 ! *confirm_msg = '\n';
210 ! STRCPY(confirm_msg + 1, message);
212 ! p = confirm_msg + 1 + STRLEN(message);
215 ! *q = (char_u)TOLOWER_LOC(*r); /* define lowercase hotkey */
217 ! /* Remember where the choices start, displaying starts here when "q" typed
218 ! * at the more prompt. */
219 ! confirm_msg_tail = p;
224 ! if (*r == DLG_BUTTON_SEP)
227 ! *p++ = ' '; /* '\n' -> ', ' */
228 ! *(++q) = (char_u)TOLOWER_LOC(*(r + 1)); /* next hotkey */
232 ! else if (*r == DLG_HOTKEY_CHAR)
235 ! if (*r == DLG_HOTKEY_CHAR) /* '&&a' -> '&a' */
239 ! /* '&a' -> '[a]' */
240 ! *p++ = (dfltbutton == 1) ? '[' : '(';
242 ! *p++ = (dfltbutton == 1) ? ']' : ')';
243 ! *q = (char_u)TOLOWER_LOC(*r); /* define lowercase hotkey */
248 ! *p++ = *r; /* everything else copy literally */
257 display_confirm_msg();
264 ! # define HOTK_LEN (has_mbyte ? MB_MAXBYTES : 1)
266 ! # define HOTK_LEN 1
268 ! int lenhotkey = HOTK_LEN; /* count first button */
269 ! char_u *hotk = NULL;
270 ! char_u *msgp = NULL;
271 ! char_u *hotkp = NULL;
274 + #define HAS_HOTKEY_LEN 30
275 + char_u has_hotkey[HAS_HOTKEY_LEN];
276 + int first_hotkey = FALSE; /* first char of button is hotkey */
279 + has_hotkey[0] = FALSE;
282 ! * First loop: compute the size of memory to allocate.
283 ! * Second loop: copy to the allocated memory.
285 ! for (copy = 0; copy <= 1; ++copy)
291 ! if (*r == DLG_BUTTON_SEP)
296 ! *msgp++ = ' '; /* '\n' -> ', ' */
298 ! /* advance to next hotkey and set default hotkey */
301 ! hotkp += (*mb_ptr2len_check)(hotkp);
305 ! (void)copy_char(r + 1, hotkp, TRUE);
309 ! /* If no hotkey is specified first char is used. */
310 ! if (idx < HAS_HOTKEY_LEN - 1 && !has_hotkey[++idx])
311 ! first_hotkey = TRUE;
315 ! len += 3; /* '\n' -> ', '; 'x' -> '(x)' */
316 ! lenhotkey += HOTK_LEN; /* each button needs a hotkey */
317 ! if (idx < HAS_HOTKEY_LEN - 1)
318 ! has_hotkey[++idx] = FALSE;
321 ! else if (*r == DLG_HOTKEY_CHAR || first_hotkey)
323 ! if (*r == DLG_HOTKEY_CHAR)
325 ! first_hotkey = FALSE;
328 ! if (*r == DLG_HOTKEY_CHAR) /* '&&a' -> '&a' */
332 ! /* '&a' -> '[a]' */
333 ! *msgp++ = (dfltbutton == 1) ? '[' : '(';
334 ! msgp += copy_char(r, msgp, FALSE);
335 ! *msgp++ = (dfltbutton == 1) ? ']' : ')';
337 ! /* redefine hotkey */
338 ! (void)copy_char(r, hotkp, TRUE);
343 ! ++len; /* '&a' -> '[a]' */
344 ! if (idx < HAS_HOTKEY_LEN - 1)
345 ! has_hotkey[idx] = TRUE;
350 ! /* everything else copy literally */
352 ! msgp += copy_char(r, msgp, FALSE);
355 ! /* advance to the next character */
358 ! r += (*mb_ptr2len_check)(r);
371 ! hotkp += (*mb_ptr2len_check)(hotkp);
379 ! len += STRLEN(message)
380 ! + 2 /* for the NL's */
382 ! + 3; /* for the ": " and NUL */
383 ! lenhotkey++; /* for the NUL */
386 ! * Now allocate and load the strings
388 ! vim_free(confirm_msg);
389 ! confirm_msg = alloc(len);
390 ! if (confirm_msg == NULL)
392 ! *confirm_msg = NUL;
393 ! hotk = alloc(lenhotkey);
397 ! *confirm_msg = '\n';
398 ! STRCPY(confirm_msg + 1, message);
400 ! msgp = confirm_msg + 1 + STRLEN(message);
403 ! /* define first default hotkey */
404 ! (void)copy_char(buttons, hotkp, TRUE);
406 ! /* If no hotkey is specified first char is used. */
407 ! if (!has_hotkey[0])
408 ! first_hotkey = TRUE;
410 ! /* Remember where the choices start, displaying starts here when
411 ! * "hotkp" typed at the more prompt. */
412 ! confirm_msg_tail = msgp;
417 display_confirm_msg();
419 *** ../vim-6.2.205/src/macros.h Sat Sep 27 19:36:47 2003
420 --- src/macros.h Thu Jan 22 14:33:13 2004
425 * MB_ISLOWER() and MB_ISUPPER() are to be used on multi-byte characters. But
426 ! * don't use them for negative values or values above 0x100 for DBCS.
429 ! # define MB_ISLOWER(c) (enc_utf8 && (c) > 0x80 ? utf_islower(c) : islower(c))
430 ! # define MB_ISUPPER(c) (enc_utf8 && (c) > 0x80 ? utf_isupper(c) : isupper(c))
431 ! # define MB_TOLOWER(c) (enc_utf8 && (c) > 0x80 ? utf_tolower(c) : TOLOWER_LOC(c))
432 ! # define MB_TOUPPER(c) (enc_utf8 && (c) > 0x80 ? utf_toupper(c) : TOUPPER_LOC(c))
434 # define MB_ISLOWER(c) islower(c)
435 # define MB_ISUPPER(c) isupper(c)
439 * MB_ISLOWER() and MB_ISUPPER() are to be used on multi-byte characters. But
440 ! * don't use them for negative values.
443 ! # define MB_ISLOWER(c) (enc_utf8 && (c) > 0x80 ? utf_islower(c) : (has_mbyte && c > 255 ? FALSE : islower(c)))
444 ! # define MB_ISUPPER(c) (enc_utf8 && (c) > 0x80 ? utf_isupper(c) : (has_mbyte && c > 255 ? FALSE : isupper(c)))
445 ! # define MB_TOLOWER(c) (enc_utf8 && (c) > 0x80 ? utf_tolower(c) : (has_mbyte && c > 255 ? c : TOLOWER_LOC(c)))
446 ! # define MB_TOUPPER(c) (enc_utf8 && (c) > 0x80 ? utf_toupper(c) : (has_mbyte && c > 255 ? c : TOUPPER_LOC(c)))
448 # define MB_ISLOWER(c) islower(c)
449 # define MB_ISUPPER(c) isupper(c)
450 *** ../vim-6.2.205/src/version.c Sun Jan 25 20:24:03 2004
451 --- src/version.c Sun Jan 25 20:26:14 2004
455 { /* Add new patch number below this line */
461 "I love deadlines. I especially like the whooshing sound they
462 make as they go flying by."
465 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
466 /// Sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
467 \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
468 \\\ Help AIDS victims, buy here: http://ICCF-Holland.org/click1.html ///