+/* Record the starting position START and METHOD of one composition. */
+
+#define CODING_ADD_COMPOSITION_START(coding, start, method) \
+ do { \
+ struct composition_data *cmp_data = coding->cmp_data; \
+ int *data = cmp_data->data + cmp_data->used; \
+ coding->cmp_data_start = cmp_data->used; \
+ data[0] = -1; \
+ data[1] = cmp_data->char_offset + start; \
+ data[3] = (int) method; \
+ cmp_data->used += 4; \
+ } while (0)
+
+/* Record the ending position END of the current composition. */
+
+#define CODING_ADD_COMPOSITION_END(coding, end) \
+ do { \
+ struct composition_data *cmp_data = coding->cmp_data; \
+ int *data = cmp_data->data + coding->cmp_data_start; \
+ data[0] = cmp_data->used - coding->cmp_data_start; \
+ data[2] = cmp_data->char_offset + end; \
+ } while (0)
+
+/* Record one COMPONENT (alternate character or composition rule). */
+
+#define CODING_ADD_COMPOSITION_COMPONENT(coding, component) \
+ (coding->cmp_data->data[coding->cmp_data->used++] = component)
+
+
+/* Get one byte from a data pointed by SRC and increment SRC. If SRC
+ is not less than SRC_END, return -1 without inccrementing Src. */
+
+#define SAFE_ONE_MORE_BYTE() (src >= src_end ? -1 : *src++)
+
+
+/* Decode a character represented as a component of composition
+ sequence of Emacs 20 style at SRC. Set C to that character, store
+ its multibyte form sequence at P, and set P to the end of that
+ sequence. If no valid character is found, set C to -1. */
+
+#define DECODE_EMACS_MULE_COMPOSITION_CHAR(c, p) \
+ do { \
+ int bytes; \
+ \
+ c = SAFE_ONE_MORE_BYTE (); \
+ if (c < 0) \
+ break; \
+ if (CHAR_HEAD_P (c)) \
+ c = -1; \
+ else if (c == 0xA0) \
+ { \
+ c = SAFE_ONE_MORE_BYTE (); \
+ if (c < 0xA0) \
+ c = -1; \
+ else \
+ { \
+ c -= 0xA0; \
+ *p++ = c; \
+ } \
+ } \
+ else if (BASE_LEADING_CODE_P (c - 0x20)) \
+ { \
+ unsigned char *p0 = p; \
+ \
+ c -= 0x20; \
+ *p++ = c; \
+ bytes = BYTES_BY_CHAR_HEAD (c); \
+ while (--bytes) \
+ { \
+ c = SAFE_ONE_MORE_BYTE (); \
+ if (c < 0) \
+ break; \
+ *p++ = c; \
+ } \
+ if (UNIBYTE_STR_AS_MULTIBYTE_P (p0, p - p0, bytes)) \
+ c = STRING_CHAR (p0, bytes); \
+ else \
+ c = -1; \
+ } \
+ else \
+ c = -1; \
+ } while (0)
+
+
+/* Decode a composition rule represented as a component of composition
+ sequence of Emacs 20 style at SRC. Set C to the rule. If not
+ valid rule is found, set C to -1. */
+
+#define DECODE_EMACS_MULE_COMPOSITION_RULE(c) \
+ do { \
+ c = SAFE_ONE_MORE_BYTE (); \
+ c -= 0xA0; \
+ if (c < 0 || c >= 81) \
+ c = -1; \
+ else \
+ { \
+ gref = c / 9, nref = c % 9; \
+ c = COMPOSITION_ENCODE_RULE (gref, nref); \
+ } \
+ } while (0)
+
+
+/* Decode composition sequence encoded by `emacs-mule' at the source
+ pointed by SRC. SRC_END is the end of source. Store information
+ of the composition in CODING->cmp_data.
+
+ For backward compatibility, decode also a composition sequence of
+ Emacs 20 style. In that case, the composition sequence contains
+ characters that should be extracted into a buffer or string. Store
+ those characters at *DESTINATION in multibyte form.
+
+ If we encounter an invalid byte sequence, return 0.
+ If we encounter an insufficient source or destination, or
+ insufficient space in CODING->cmp_data, return 1.
+ Otherwise, return consumed bytes in the source.
+
+*/
+static INLINE int
+decode_composition_emacs_mule (coding, src, src_end,
+ destination, dst_end, dst_bytes)
+ struct coding_system *coding;
+ unsigned char *src, *src_end, **destination, *dst_end;
+ int dst_bytes;
+{
+ unsigned char *dst = *destination;
+ int method, data_len, nchars;
+ unsigned char *src_base = src++;
+ /* Store compoments of composition. */
+ int component[COMPOSITION_DATA_MAX_BUNCH_LENGTH];
+ int ncomponent;
+ /* Store multibyte form of characters to be composed. This is for
+ Emacs 20 style composition sequence. */
+ unsigned char buf[MAX_COMPOSITION_COMPONENTS * MAX_MULTIBYTE_LENGTH];
+ unsigned char *bufp = buf;
+ int c, i, gref, nref;
+
+ if (coding->cmp_data->used + COMPOSITION_DATA_MAX_BUNCH_LENGTH
+ >= COMPOSITION_DATA_SIZE)
+ {
+ coding->result = CODING_FINISH_INSUFFICIENT_CMP;
+ return -1;
+ }
+
+ ONE_MORE_BYTE (c);
+ if (c - 0xF0 >= COMPOSITION_RELATIVE
+ && c - 0xF0 <= COMPOSITION_WITH_RULE_ALTCHARS)
+ {
+ int with_rule;
+
+ method = c - 0xF0;
+ with_rule = (method == COMPOSITION_WITH_RULE
+ || method == COMPOSITION_WITH_RULE_ALTCHARS);
+ ONE_MORE_BYTE (c);
+ data_len = c - 0xA0;
+ if (data_len < 4
+ || src_base + data_len > src_end)
+ return 0;
+ ONE_MORE_BYTE (c);
+ nchars = c - 0xA0;
+ if (c < 1)
+ return 0;
+ for (ncomponent = 0; src < src_base + data_len; ncomponent++)
+ {
+ if (ncomponent % 2 && with_rule)
+ {
+ ONE_MORE_BYTE (gref);
+ gref -= 32;
+ ONE_MORE_BYTE (nref);
+ nref -= 32;
+ c = COMPOSITION_ENCODE_RULE (gref, nref);
+ }
+ else
+ {
+ int bytes;
+ if (UNIBYTE_STR_AS_MULTIBYTE_P (src, src_end - src, bytes))
+ c = STRING_CHAR (src, bytes);
+ else
+ c = *src, bytes = 1;
+ src += bytes;
+ }
+ component[ncomponent] = c;
+ }
+ }
+ else
+ {
+ /* This may be an old Emacs 20 style format. See the comment at
+ the section 2 of this file. */
+ while (src < src_end && !CHAR_HEAD_P (*src)) src++;
+ if (src == src_end
+ && !(coding->mode & CODING_MODE_LAST_BLOCK))
+ goto label_end_of_loop;
+
+ src_end = src;
+ src = src_base + 1;
+ if (c < 0xC0)
+ {
+ method = COMPOSITION_RELATIVE;
+ for (ncomponent = 0; ncomponent < MAX_COMPOSITION_COMPONENTS;)
+ {
+ DECODE_EMACS_MULE_COMPOSITION_CHAR (c, bufp);
+ if (c < 0)
+ break;
+ component[ncomponent++] = c;
+ }
+ if (ncomponent < 2)
+ return 0;
+ nchars = ncomponent;
+ }
+ else if (c == 0xFF)
+ {
+ method = COMPOSITION_WITH_RULE;
+ src++;
+ DECODE_EMACS_MULE_COMPOSITION_CHAR (c, bufp);
+ if (c < 0)
+ return 0;
+ component[0] = c;
+ for (ncomponent = 1;
+ ncomponent < MAX_COMPOSITION_COMPONENTS * 2 - 1;)
+ {
+ DECODE_EMACS_MULE_COMPOSITION_RULE (c);
+ if (c < 0)
+ break;
+ component[ncomponent++] = c;
+ DECODE_EMACS_MULE_COMPOSITION_CHAR (c, bufp);
+ if (c < 0)
+ break;
+ component[ncomponent++] = c;
+ }
+ if (ncomponent < 3)
+ return 0;
+ nchars = (ncomponent + 1) / 2;
+ }
+ else
+ return 0;
+ }
+
+ if (buf == bufp || dst + (bufp - buf) <= (dst_bytes ? dst_end : src))
+ {
+ CODING_ADD_COMPOSITION_START (coding, coding->produced_char, method);
+ for (i = 0; i < ncomponent; i++)
+ CODING_ADD_COMPOSITION_COMPONENT (coding, component[i]);
+ CODING_ADD_COMPOSITION_END (coding, coding->produced_char + nchars);
+ if (buf < bufp)
+ {
+ unsigned char *p = buf;
+ EMIT_BYTES (p, bufp);
+ *destination += bufp - buf;
+ coding->produced_char += nchars;
+ }
+ return (src - src_base);
+ }
+ label_end_of_loop:
+ return -1;
+}
+