+static void
+merge_print_line (const char *line, const char *p, FILE *stream)
+{
+ char *buf = NULL;
+ char *merged_esc = NULL;
+ const char *esc = "";
+ const char char_restore = *p;
+
+ complete_part_line (p + 1, &buf, stream);
+
+ if (buf)
+ {
+ /* form escape sequence */
+ esc = merged_esc = str_concat (p, buf);
+ /* shorten partial line accordingly */
+ *(char *)p = '\0';
+ free (buf);
+ }
+
+#ifdef TEST_MERGE_PART_LINE
+ printf ("%s%s", line, esc);
+ fflush (stdout);
+ _exit (EXIT_SUCCESS);
+#else
+ print_clean (line);
+ *(char *)p = char_restore;
+ print_clean (esc);
+ free (merged_esc);
+#endif
+}
+
+static void
+complete_part_line (const char *p, char **buf, FILE *stream)
+{
+ bool got_next_char = false, read_from_stream;
+ char ch;
+ size_t i = 0, size;
+
+ if (get_next_char (&ch, &p, stream, &read_from_stream))
+ {
+ if (ch == '[')
+ {
+ if (read_from_stream)
+ save_char (ch, buf, &i, &size);
+ }
+ else
+ {
+ if (read_from_stream)
+ ungetc ((int)ch, stream);
+ return; /* cancel */
+ }
+ }
+ else
+ return; /* cancel */
+
+ while (get_next_char (&ch, &p, stream, &read_from_stream))
+ {
+ if (isdigit (ch) || ch == ';')
+ {
+ if (read_from_stream)
+ save_char (ch, buf, &i, &size);
+ }
+ else /* got next character */
+ {
+ got_next_char = true;
+ break;
+ }
+ }
+
+ if (got_next_char)
+ {
+ if (ch == 'm')
+ {
+ if (read_from_stream)
+ save_char (ch, buf, &i, &size);
+ }
+ else
+ {
+ if (read_from_stream)
+ ungetc ((int)ch, stream);
+ return; /* cancel */
+ }
+ }
+ else
+ return; /* cancel */
+}
+
+static bool
+get_next_char (char *ch, const char **p, FILE *stream, bool *read_from_stream)
+{
+ if (**p == '\0')
+ {
+ int c;
+ if ((c = fgetc (stream)) != EOF)
+ {
+ *ch = (char)c;
+ *read_from_stream = true;
+ return true;
+ }
+ else
+ {
+ *read_from_stream = false;
+ return false;
+ }
+ }
+ else
+ {
+ *ch = **p;
+ (*p)++;
+ *read_from_stream = false;
+ return true;
+ }
+}
+
+static void
+save_char (char ch, char **buf, size_t *i, size_t *size)
+{
+ if (!*buf)
+ {
+ *size = ALLOC_COMPLETE_PART_LINE;
+ *buf = xmalloc (*size);
+ }
+ /* +1: effective occupied size of buffer */
+ else if ((*i + 1) == *size)
+ {
+ *size *= 2;
+ *buf = xrealloc (*buf, *size);
+ }
+ (*buf)[*i] = ch;
+ (*buf)[*i + 1] = '\0';
+ (*i)++;
+}
+