+/* Translate (in place) %_ to &, %% to %.
+ Return new length, and (through accel) the accelerator character.
+ (If there is no accelerator, it will be added on the first character.)
+ len = number of bytes (not including zero terminator).
+ maxlen = size of buffer.
+ We assume and maintain zero-termination. To be absolutely sure
+ of not hitting an error, maxlen should be >= 2*len + 3. */
+
+Bytecount
+msw_translate_menu_or_dialog_item (Bufbyte *item, Bytecount len,
+ Bytecount maxlen, Emchar *accel,
+ Lisp_Object error_name)
+{
+ Bufbyte *ptr;
+
+ *accel = '\0';
+
+ /* Escape '&' as '&&' */
+
+ ptr = item;
+ while ((ptr = (Bufbyte *) memchr (ptr, '&', len - (ptr - item))) != NULL)
+ {
+ if (len + 2 > maxlen)
+ signal_simple_error ("Menu item produces too long displayable string",
+ error_name);
+ memmove (ptr + 1, ptr, (len - (ptr - item)) + 1);
+ len++;
+ ptr += 2;
+ }
+
+ /* Replace XEmacs accelerator '%_' with Windows accelerator '&'
+ and `%%' with `%'. */
+ ptr = item;
+ while ((ptr = memchr (ptr, '%', len - (ptr - item))) != NULL)
+ {
+ if (*(ptr + 1) == '_')
+ {
+ *ptr = '&';
+ if (!*accel)
+ /* #### urk ! We need a reference translation table for
+ case changes that aren't buffer-specific. */
+ *accel = DOWNCASE (current_buffer, charptr_emchar (ptr + 2));
+ memmove (ptr + 1, ptr + 2, len - (ptr - item + 2) + 1);
+ len--;
+ }
+ else if (*(ptr + 1) == '%')
+ {
+ memmove (ptr + 1, ptr + 2, len - (ptr - item + 2) + 1);
+ len--;
+ }
+ ptr++;
+ }
+
+ if (!*accel)
+ {
+ if (len + 2 > maxlen)
+ signal_simple_error ("Menu item produces too long displayable string",
+ error_name);
+ ptr = item;
+ memmove (ptr + 1, ptr, len + 1);
+ /* #### urk ! We need a reference translation table for
+ case changes that aren't buffer-specific. */
+ *accel = DOWNCASE (current_buffer, charptr_emchar (ptr + 1));
+ *ptr = '&';
+
+ len++;
+ }
+
+ return len;
+}