]>
Commit | Line | Data |
---|---|---|
d02ad552 AG |
1 | To: vim-dev@vim.org |
2 | Subject: Patch 6.2.206 | |
3 | Fcc: outbox | |
4 | From: Bram Moolenaar <Bram@moolenaar.net> | |
5 | Mime-Version: 1.0 | |
6 | Content-Type: text/plain; charset=ISO-8859-1 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ------------ | |
9 | ||
10 | Patch 6.2.206 | |
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 | |
14 | default hotkeys. | |
15 | Files: src/message.c, src/macros.h | |
16 | ||
17 | ||
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 | |
20 | *************** | |
21 | *** 2536,2541 **** | |
22 | --- 2536,2542 ---- | |
23 | int retval = 0; | |
24 | char_u *hotkeys; | |
25 | int c; | |
26 | + int i; | |
27 | ||
28 | #ifndef NO_CONSOLE | |
29 | /* Don't output anything in silent mode ("ex -s") */ | |
30 | *************** | |
31 | *** 2579,2601 **** | |
32 | case NL: | |
33 | retval = dfltbutton; | |
34 | break; | |
35 | ! case Ctrl_C: /* User aborts/cancels */ | |
36 | case ESC: | |
37 | retval = 0; | |
38 | break; | |
39 | default: /* Could be a hotkey? */ | |
40 | ! if (c > 255) /* special keys are ignored here */ | |
41 | continue; | |
42 | ! for (retval = 0; hotkeys[retval]; retval++) | |
43 | { | |
44 | ! if (hotkeys[retval] == TOLOWER_LOC(c)) | |
45 | ! break; | |
46 | } | |
47 | ! if (hotkeys[retval]) | |
48 | ! { | |
49 | ! retval++; | |
50 | break; | |
51 | - } | |
52 | /* No hotkey match, so keep waiting */ | |
53 | continue; | |
54 | } | |
55 | --- 2580,2612 ---- | |
56 | case NL: | |
57 | retval = dfltbutton; | |
58 | break; | |
59 | ! case Ctrl_C: /* User aborts/cancels */ | |
60 | case ESC: | |
61 | retval = 0; | |
62 | break; | |
63 | default: /* Could be a hotkey? */ | |
64 | ! if (c < 0) /* special keys are ignored here */ | |
65 | continue; | |
66 | ! /* Make the character lowercase, as chars in "hotkeys" are. */ | |
67 | ! c = MB_TOLOWER(c); | |
68 | ! retval = 1; | |
69 | ! for (i = 0; hotkeys[i]; ++i) | |
70 | { | |
71 | ! #ifdef FEAT_MBYTE | |
72 | ! if (has_mbyte) | |
73 | ! { | |
74 | ! if ((*mb_ptr2char)(hotkeys + i) == c) | |
75 | ! break; | |
76 | ! i += (*mb_ptr2len_check)(hotkeys + i) - 1; | |
77 | ! } | |
78 | ! else | |
79 | ! #endif | |
80 | ! if (hotkeys[i] == c) | |
81 | ! break; | |
82 | ! ++retval; | |
83 | } | |
84 | ! if (hotkeys[i]) | |
85 | break; | |
86 | /* No hotkey match, so keep waiting */ | |
87 | continue; | |
88 | } | |
89 | *************** | |
90 | *** 2615,2628 **** | |
91 | return retval; | |
92 | } | |
93 | ||
94 | /* | |
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. | |
99 | ! * | |
100 | ! * Returns allocated array, or NULL for error. | |
101 | * | |
102 | */ | |
103 | static char_u * | |
104 | msg_show_console_dialog(message, buttons, dfltbutton) | |
105 | --- 2626,2680 ---- | |
106 | return retval; | |
107 | } | |
108 | ||
109 | + static int copy_char __ARGS((char_u *from, char_u *to, int lowercase)); | |
110 | + | |
111 | + /* | |
112 | + * Copy one character from "*from" to "*to", taking care of multi-byte | |
113 | + * characters. Return the length of the character in bytes. | |
114 | + */ | |
115 | + static int | |
116 | + copy_char(from, to, lowercase) | |
117 | + char_u *from; | |
118 | + char_u *to; | |
119 | + int lowercase; /* make character lower case */ | |
120 | + { | |
121 | + #ifdef FEAT_MBYTE | |
122 | + int len; | |
123 | + int c; | |
124 | + | |
125 | + if (has_mbyte) | |
126 | + { | |
127 | + if (lowercase) | |
128 | + { | |
129 | + c = MB_TOLOWER((*mb_ptr2char)(from)); | |
130 | + return (*mb_char2bytes)(c, to); | |
131 | + } | |
132 | + else | |
133 | + { | |
134 | + len = (*mb_ptr2len_check)(from); | |
135 | + mch_memmove(to, from, (size_t)len); | |
136 | + return len; | |
137 | + } | |
138 | + } | |
139 | + else | |
140 | + #endif | |
141 | + { | |
142 | + if (lowercase) | |
143 | + *to = (char_u)TOLOWER_LOC(*from); | |
144 | + else | |
145 | + *to = *from; | |
146 | + return 1; | |
147 | + } | |
148 | + } | |
149 | + | |
150 | /* | |
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. | |
156 | * | |
157 | + * Returns an allocated string with hotkeys, or NULL for error. | |
158 | */ | |
159 | static char_u * | |
160 | msg_show_console_dialog(message, buttons, dfltbutton) | |
161 | *************** | |
162 | *** 2631,2726 **** | |
163 | int dfltbutton; | |
164 | { | |
165 | int len = 0; | |
166 | ! int lenhotkey = 1; /*first button*/ | |
167 | ! char_u *hotk; | |
168 | ! char_u *p; | |
169 | ! char_u *q; | |
170 | char_u *r; | |
171 | ||
172 | /* | |
173 | ! * First compute how long a string we need to allocate for the message. | |
174 | */ | |
175 | ! r = buttons; | |
176 | ! while (*r) | |
177 | { | |
178 | ! if (*r == DLG_BUTTON_SEP) | |
179 | { | |
180 | ! len++; /* '\n' -> ', ' */ | |
181 | ! lenhotkey++; /* each button needs a hotkey */ | |
182 | ! } | |
183 | ! else if (*r == DLG_HOTKEY_CHAR) | |
184 | ! { | |
185 | ! len++; /* '&a' -> '[a]' */ | |
186 | ! } | |
187 | ! r++; | |
188 | ! } | |
189 | ! | |
190 | ! len += STRLEN(message) | |
191 | ! + 2 /* for the NL's */ | |
192 | ! + STRLEN(buttons) | |
193 | ! + 3; /* for the ": " and NUL */ | |
194 | ||
195 | ! lenhotkey++; /* for the NUL */ | |
196 | ||
197 | ! /* | |
198 | ! * Now allocate and load the strings | |
199 | ! */ | |
200 | ! vim_free(confirm_msg); | |
201 | ! confirm_msg = alloc(len); | |
202 | ! if (confirm_msg == NULL) | |
203 | ! return NULL; | |
204 | ! *confirm_msg = NUL; | |
205 | ! hotk = alloc(lenhotkey); | |
206 | ! if (hotk == NULL) | |
207 | ! return NULL; | |
208 | ! | |
209 | ! *confirm_msg = '\n'; | |
210 | ! STRCPY(confirm_msg + 1, message); | |
211 | ! | |
212 | ! p = confirm_msg + 1 + STRLEN(message); | |
213 | ! q = hotk; | |
214 | ! r = buttons; | |
215 | ! *q = (char_u)TOLOWER_LOC(*r); /* define lowercase hotkey */ | |
216 | ! | |
217 | ! /* Remember where the choices start, displaying starts here when "q" typed | |
218 | ! * at the more prompt. */ | |
219 | ! confirm_msg_tail = p; | |
220 | ! *p++ = '\n'; | |
221 | ||
222 | ! while (*r) | |
223 | ! { | |
224 | ! if (*r == DLG_BUTTON_SEP) | |
225 | { | |
226 | ! *p++ = ','; | |
227 | ! *p++ = ' '; /* '\n' -> ', ' */ | |
228 | ! *(++q) = (char_u)TOLOWER_LOC(*(r + 1)); /* next hotkey */ | |
229 | ! if (dfltbutton) | |
230 | ! --dfltbutton; | |
231 | ! } | |
232 | ! else if (*r == DLG_HOTKEY_CHAR) | |
233 | ! { | |
234 | ! r++; | |
235 | ! if (*r == DLG_HOTKEY_CHAR) /* '&&a' -> '&a' */ | |
236 | ! *p++ = *r; | |
237 | else | |
238 | ! { | |
239 | ! /* '&a' -> '[a]' */ | |
240 | ! *p++ = (dfltbutton == 1) ? '[' : '('; | |
241 | ! *p++ = *r; | |
242 | ! *p++ = (dfltbutton == 1) ? ']' : ')'; | |
243 | ! *q = (char_u)TOLOWER_LOC(*r); /* define lowercase hotkey */ | |
244 | ! } | |
245 | } | |
246 | else | |
247 | { | |
248 | ! *p++ = *r; /* everything else copy literally */ | |
249 | } | |
250 | - r++; | |
251 | } | |
252 | - *p++ = ':'; | |
253 | - *p++ = ' '; | |
254 | - *p = NUL; | |
255 | - *(++q) = NUL; | |
256 | ||
257 | display_confirm_msg(); | |
258 | return hotk; | |
259 | --- 2683,2841 ---- | |
260 | int dfltbutton; | |
261 | { | |
262 | int len = 0; | |
263 | ! #ifdef FEAT_MBYTE | |
264 | ! # define HOTK_LEN (has_mbyte ? MB_MAXBYTES : 1) | |
265 | ! #else | |
266 | ! # define HOTK_LEN 1 | |
267 | ! #endif | |
268 | ! int lenhotkey = HOTK_LEN; /* count first button */ | |
269 | ! char_u *hotk = NULL; | |
270 | ! char_u *msgp = NULL; | |
271 | ! char_u *hotkp = NULL; | |
272 | char_u *r; | |
273 | + int copy; | |
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 */ | |
277 | + int idx; | |
278 | + | |
279 | + has_hotkey[0] = FALSE; | |
280 | ||
281 | /* | |
282 | ! * First loop: compute the size of memory to allocate. | |
283 | ! * Second loop: copy to the allocated memory. | |
284 | */ | |
285 | ! for (copy = 0; copy <= 1; ++copy) | |
286 | { | |
287 | ! r = buttons; | |
288 | ! idx = 0; | |
289 | ! while (*r) | |
290 | { | |
291 | ! if (*r == DLG_BUTTON_SEP) | |
292 | ! { | |
293 | ! if (copy) | |
294 | ! { | |
295 | ! *msgp++ = ','; | |
296 | ! *msgp++ = ' '; /* '\n' -> ', ' */ | |
297 | ||
298 | ! /* advance to next hotkey and set default hotkey */ | |
299 | ! #ifdef FEAT_MBYTE | |
300 | ! if (has_mbyte) | |
301 | ! hotkp += (*mb_ptr2len_check)(hotkp); | |
302 | ! else | |
303 | ! #endif | |
304 | ! ++hotkp; | |
305 | ! (void)copy_char(r + 1, hotkp, TRUE); | |
306 | ! if (dfltbutton) | |
307 | ! --dfltbutton; | |
308 | ! | |
309 | ! /* If no hotkey is specified first char is used. */ | |
310 | ! if (idx < HAS_HOTKEY_LEN - 1 && !has_hotkey[++idx]) | |
311 | ! first_hotkey = TRUE; | |
312 | ! } | |
313 | ! else | |
314 | ! { | |
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; | |
319 | ! } | |
320 | ! } | |
321 | ! else if (*r == DLG_HOTKEY_CHAR || first_hotkey) | |
322 | ! { | |
323 | ! if (*r == DLG_HOTKEY_CHAR) | |
324 | ! ++r; | |
325 | ! first_hotkey = FALSE; | |
326 | ! if (copy) | |
327 | ! { | |
328 | ! if (*r == DLG_HOTKEY_CHAR) /* '&&a' -> '&a' */ | |
329 | ! *msgp++ = *r; | |
330 | ! else | |
331 | ! { | |
332 | ! /* '&a' -> '[a]' */ | |
333 | ! *msgp++ = (dfltbutton == 1) ? '[' : '('; | |
334 | ! msgp += copy_char(r, msgp, FALSE); | |
335 | ! *msgp++ = (dfltbutton == 1) ? ']' : ')'; | |
336 | ! | |
337 | ! /* redefine hotkey */ | |
338 | ! (void)copy_char(r, hotkp, TRUE); | |
339 | ! } | |
340 | ! } | |
341 | ! else | |
342 | ! { | |
343 | ! ++len; /* '&a' -> '[a]' */ | |
344 | ! if (idx < HAS_HOTKEY_LEN - 1) | |
345 | ! has_hotkey[idx] = TRUE; | |
346 | ! } | |
347 | ! } | |
348 | ! else | |
349 | ! { | |
350 | ! /* everything else copy literally */ | |
351 | ! if (copy) | |
352 | ! msgp += copy_char(r, msgp, FALSE); | |
353 | ! } | |
354 | ||
355 | ! /* advance to the next character */ | |
356 | ! #ifdef FEAT_MBYTE | |
357 | ! if (has_mbyte) | |
358 | ! r += (*mb_ptr2len_check)(r); | |
359 | ! else | |
360 | ! #endif | |
361 | ! ++r; | |
362 | ! } | |
363 | ||
364 | ! if (copy) | |
365 | { | |
366 | ! *msgp++ = ':'; | |
367 | ! *msgp++ = ' '; | |
368 | ! *msgp = NUL; | |
369 | ! #ifdef FEAT_MBYTE | |
370 | ! if (has_mbyte) | |
371 | ! hotkp += (*mb_ptr2len_check)(hotkp); | |
372 | else | |
373 | ! #endif | |
374 | ! ++hotkp; | |
375 | ! *hotkp = NUL; | |
376 | } | |
377 | else | |
378 | { | |
379 | ! len += STRLEN(message) | |
380 | ! + 2 /* for the NL's */ | |
381 | ! + STRLEN(buttons) | |
382 | ! + 3; /* for the ": " and NUL */ | |
383 | ! lenhotkey++; /* for the NUL */ | |
384 | ! | |
385 | ! /* | |
386 | ! * Now allocate and load the strings | |
387 | ! */ | |
388 | ! vim_free(confirm_msg); | |
389 | ! confirm_msg = alloc(len); | |
390 | ! if (confirm_msg == NULL) | |
391 | ! return NULL; | |
392 | ! *confirm_msg = NUL; | |
393 | ! hotk = alloc(lenhotkey); | |
394 | ! if (hotk == NULL) | |
395 | ! return NULL; | |
396 | ! | |
397 | ! *confirm_msg = '\n'; | |
398 | ! STRCPY(confirm_msg + 1, message); | |
399 | ! | |
400 | ! msgp = confirm_msg + 1 + STRLEN(message); | |
401 | ! hotkp = hotk; | |
402 | ! | |
403 | ! /* define first default hotkey */ | |
404 | ! (void)copy_char(buttons, hotkp, TRUE); | |
405 | ! | |
406 | ! /* If no hotkey is specified first char is used. */ | |
407 | ! if (!has_hotkey[0]) | |
408 | ! first_hotkey = TRUE; | |
409 | ! | |
410 | ! /* Remember where the choices start, displaying starts here when | |
411 | ! * "hotkp" typed at the more prompt. */ | |
412 | ! confirm_msg_tail = msgp; | |
413 | ! *msgp++ = '\n'; | |
414 | } | |
415 | } | |
416 | ||
417 | display_confirm_msg(); | |
418 | return hotk; | |
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 | |
421 | *************** | |
422 | *** 81,93 **** | |
423 | ||
424 | /* | |
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. | |
427 | */ | |
428 | #ifdef FEAT_MBYTE | |
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)) | |
433 | #else | |
434 | # define MB_ISLOWER(c) islower(c) | |
435 | # define MB_ISUPPER(c) isupper(c) | |
436 | --- 81,93 ---- | |
437 | ||
438 | /* | |
439 | * MB_ISLOWER() and MB_ISUPPER() are to be used on multi-byte characters. But | |
440 | ! * don't use them for negative values. | |
441 | */ | |
442 | #ifdef FEAT_MBYTE | |
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))) | |
447 | #else | |
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 | |
452 | *************** | |
453 | *** 639,640 **** | |
454 | --- 639,642 ---- | |
455 | { /* Add new patch number below this line */ | |
456 | + /**/ | |
457 | + 206, | |
458 | /**/ | |
459 | ||
460 | -- | |
461 | "I love deadlines. I especially like the whooshing sound they | |
462 | make as they go flying by." | |
463 | -- Douglas Adams | |
464 | ||
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 /// |