+/*
+ * Compile our format string and save any parameters we care about.
+ */
+
+#define DEFAULT_MARKER "[ part %{part} - %{content-type} - %<{description}" \
+ "%{description}%?{cdispo-filename}%{cdispo-filename}" \
+ "%|%{ctype-name}%> ]"
+
+static struct format *
+compile_marker(char *markerform, char *markerformat)
+{
+ struct format *fmt;
+ char *fmtstring;
+ struct comp *comp = NULL;
+ unsigned int bucket;
+ struct param_comp_list *pc_entry;
+
+ fmtstring = new_fs(markerform, markerformat, DEFAULT_MARKER);
+
+ (void) fmt_compile(fmtstring, &fmt, 1);
+ free(fmtstring);
+
+ /*
+ * Things we care about:
+ *
+ * part - Part name (e.g., 1.1)
+ * content-type - Content-Type
+ * description - Content-Description
+ * disposition - Content-Disposition (inline, attachment)
+ * ctype-<param> - Content-Type parameter
+ * cdispo-<param> - Content-Disposition parameter
+ */
+
+ while ((comp = fmt_nextcomp(comp, &bucket)) != NULL) {
+ if (strcasecmp(comp->c_name, "part") == 0) {
+ part_comp = comp;
+ } else if (strcasecmp(comp->c_name, "content-type") == 0) {
+ ctype_comp = comp;
+ } else if (strcasecmp(comp->c_name, "description") == 0) {
+ description_comp = comp;
+ } else if (strcasecmp(comp->c_name, "disposition") == 0) {
+ dispo_comp = comp;
+ } else if (strncasecmp(comp->c_name, "ctype-", 6) == 0 &&
+ strlen(comp->c_name) > 6) {
+ pc_entry = mh_xmalloc(sizeof(*pc_entry));
+ pc_entry->param = getcpy(comp->c_name + 6);
+ pc_entry->comp = comp;
+ pc_entry->next = ctype_pc_list;
+ ctype_pc_list = pc_entry;
+ } else if (strncasecmp(comp->c_name, "cdispo-", 7) == 0 &&
+ strlen(comp->c_name) > 7) {
+ pc_entry = mh_xmalloc(sizeof(*pc_entry));
+ pc_entry->param = getcpy(comp->c_name + 7);
+ pc_entry->comp = comp;
+ pc_entry->next = dispo_pc_list;
+ dispo_pc_list = pc_entry;
+ }
+ }
+
+ return fmt;
+}
+
+/*
+ * Output on stdout an appropriate marker for this content, using mh-format
+ */
+
+static void
+output_marker(CT ct, struct format *fmt)
+{
+ char outbuf[BUFSIZ];
+ struct param_comp_list *pcentry;
+ int dat[5];
+
+ /*
+ * Grab any items we care about.
+ */
+
+ if (ctype_comp && ct->c_ctinfo.ci_type) {
+ ctype_comp->c_text = concat(ct->c_ctinfo.ci_type, "/",
+ ct->c_ctinfo.ci_subtype, NULL);
+ }
+
+ if (part_comp && ct->c_partno) {
+ part_comp->c_text = getcpy(ct->c_partno);
+ }
+
+ if (description_comp && ct->c_descr) {
+ description_comp->c_text = getcpy(ct->c_descr);
+ }
+
+ if (dispo_comp && ct->c_dispo_type) {
+ dispo_comp->c_text = getcpy(ct->c_dispo_type);
+ }
+
+ for (pcentry = ctype_pc_list; pcentry != NULL; pcentry = pcentry->next) {
+ pcentry->comp->c_text = get_param(ct->c_ctinfo.ci_first_pm,
+ pcentry->param, '?', 0);
+ }
+
+ for (pcentry = dispo_pc_list; pcentry != NULL; pcentry = pcentry->next) {
+ pcentry->comp->c_text = get_param(ct->c_dispo_first,
+ pcentry->param, '?', 0);
+ }
+
+ fmt_scan(fmt, outbuf, sizeof(outbuf), sizeof(outbuf), dat, NULL);
+
+ fputs(outbuf, stdout);
+
+ fmt_freecomptext();
+}
+
+/*
+ * Reset (and free) any of the saved marker text
+ */
+
+static void
+free_markercomps(void)
+{
+ struct param_comp_list *pc_entry, *pc2;
+
+ part_comp = NULL;
+ ctype_comp = NULL;
+ description_comp = NULL;
+ dispo_comp = NULL;
+
+ for (pc_entry = ctype_pc_list; pc_entry != NULL; ) {
+ free(pc_entry->param);
+ pc2 = pc_entry->next;
+ free(pc_entry);
+ pc_entry = pc2;
+ }
+
+ for (pc_entry = dispo_pc_list; pc_entry != NULL; ) {
+ free(pc_entry->param);
+ pc2 = pc_entry->next;
+ free(pc_entry);
+ pc_entry = pc2;
+ }
+}
+