+}
+
+/*
+ * Encode our specified header using quoted-printable
+ */
+
+static int
+field_encode_quoted(const char *name, char **value, int encoding,
+ const char *charset, int ascii, int encoded)
+{
+ int prefixlen = name ? strlen(name) + 2: 0, outlen = 0, column, newline = 1;
+ int charsetlen = strlen(charset), utf8;
+ char *output = NULL, *p, *q;
+
+ /*
+ * Right now we just encode the whole thing. Maybe later on we'll
+ * only encode things on a per-atom basis.
+ */
+
+ p = *value;
+
+ column = prefixlen + 2; /* Header name plus ": " */
+
+ utf8 = strcasecmp(charset, "UTF-8") == 0;
+
+ while (*p != '\0') {
+ /*
+ * Start a new line, if it's time
+ */
+ if (newline) {
+ /*
+ * If it's the start of the header, we don't need to pad it
+ *
+ * The length of the output string is ...
+ * =?charset?Q?...?= so that's 7+strlen(charset) + 1 for NUL
+ *
+ * plus 1 for every ASCII character and 3 for every eight bit
+ * or special character (eight bit characters are written as =XX).
+ *
+ */
+
+ outlen += 8 + charsetlen + ascii + 3 * encoded;
+ if (output) {
+ int curlen = q - output, i;
+ outlen += prefixlen + 1; /* Header plus \n ": " */
+ output = mh_xrealloc(output, outlen);
+ q = output + curlen;
+ *q++ = '?';
+ *q++ = '=';
+ *q++ = '\n';
+ for (i = 0; i < prefixlen; i++)
+ *q++ = ' ';
+ } else {
+ output = mh_xmalloc(outlen);
+ q = output;
+ }
+
+ q += snprintf(q, outlen - (q - output), "=?%s?Q?", charset);
+ column = prefixlen;
+ newline = 0;
+ }
+
+ /*
+ * Process each character, encoding if necessary
+ */
+
+ column++;
+
+ if (*p == ' ') {
+ *q++ = '_';
+ ascii--;
+ } else if (!qpspecial(*p)) {
+ *q++ = *p;
+ ascii--;
+ } else {
+ snprintf(q, outlen - (q - output), "=%02X", (unsigned int) *p);
+ q += 2;
+ column += 2;
+ encoded--;
+ }
+
+ p++;
+
+ /*
+ * We're not allowed more than ENCODELINELIMIT characters per line,
+ * so reserve some room for the final ?=.
+ *
+ * If prefixlen == 0, we haven't been passed in a header name, so
+ * don't ever wrap the field (we're likely doing an address).
+ */
+
+ if (prefixlen == 0)
+ continue;
+
+ if (column >= ENCODELINELIMIT - 2) {
+ newline = 1;
+ } else if (utf8) {
+ /*
+ * Okay, this is a bit weird, but to explain a bit more ...
+ *
+ * RFC 2047 prohibits the splitting of multibyte characters
+ * across encoded words. Right now we only handle the case
+ * of UTF-8, the most common multibyte encoding.
+ *
+ * p is now pointing at the next input character. If we're
+ * using UTF-8 _and_ we'd go over ENCODELINELIMIT given the
+ * length of the complete character, then trigger a newline
+ * now
+ */
+ if (column + utf8len(p) > ENCODELINELIMIT - 2) {
+ newline = 1;
+ }
+ }
+ }
+
+ strcat(q, "?=");
+
+ free(*value);
+
+ *value = output;