+ * Translate (in place) X accelerator syntax to win32 accelerator syntax.
+ * Return new length.
+ * len = number of bytes (not including zero terminator).
+ * maxlen = size of buffer.
+ * accel = (Emchar*) to receive the accelerator character
+ * or NULL to suppress accelerators in the menu or dialog item.
+ *
+ * %% is replaced with %
+ * if accel is NULL:
+ * %_ is removed.
+ * if accel is non-NULL:
+ * %_ is replaced with &.
+ * The accelerator character is passed back in *accel.
+ * (If there is no accelerator, it will be added on the first character.)
+ *
+ * We assume and maintain zero-termination. To be absolutely sure
+ * of not hitting an error, maxlen should be >= 2*len + 3.
+ */
+Bytecount
+mswindows_translate_menu_or_dialog_item (Bufbyte *item, Bytecount len,
+ Bytecount maxlen, Emchar *accel,
+ Lisp_Object error_name)
+{
+ Bufbyte *ptr;
+
+ if (accel)
+ *accel = '\0';
+
+ /* Escape '&' as '&&' */
+ ptr = item;
+ while ((ptr = (Bufbyte *) memchr (ptr, '&', len - (ptr - item))) != NULL)
+ {
+ if (len + 2 > maxlen)
+ syntax_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) == '_')
+ {
+ if (accel)
+ {
+ *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 /* Skip accelerator */
+ {
+ memmove (ptr, ptr + 2, len - (ptr - item + 2) + 1);
+ len-=2;
+ }
+ }
+ else if (*(ptr + 1) == '%')
+ {
+ memmove (ptr + 1, ptr + 2, len - (ptr - item + 2) + 1);
+ len--;
+ ptr++;
+ }
+ else /* % on its own - shouldn't happen */
+ ptr++;
+ }
+
+ if (accel && !*accel)
+ {
+ /* Force a default accelerator */
+ if (len + 2 > maxlen)
+ syntax_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;
+}
+
+/*