+ invalidate_proto (sc);
+}
+
+/* Adds a field to SC for each column in PROTO, so that SC
+ contains all of the columns in PROTO in the same order as a
+ case conforming to PROTO. The fields are added with
+ ascending direction. */
+void
+subcase_add_proto_always (struct subcase *sc, const struct caseproto *proto)
+{
+ size_t n = caseproto_get_n_widths (proto);
+ size_t i;
+
+ sc->fields = xnrealloc (sc->fields, sc->n_fields + n, sizeof *sc->fields);
+ for (i = 0; i < n; i++)
+ {
+ struct subcase_field *field = &sc->fields[sc->n_fields++];
+ field->case_index = i;
+ field->width = caseproto_get_width (proto, i);
+ field->direction = SC_ASCEND;
+ }
+ invalidate_proto (sc);
+}
+
+void
+subcase_concat (struct subcase *sc, const struct subcase *other)
+{
+ size_t i;
+
+ for (i = 0; i < other->n_fields; i++)
+ {
+ const struct subcase_field *f = &other->fields[i];
+ subcase_add (sc, f->case_index, f->width, f->direction);
+ }
+}
+
+void
+subcase_concat_always (struct subcase *sc, const struct subcase *other)
+{
+ size_t i;
+
+ for (i = 0; i < other->n_fields; i++)
+ {
+ const struct subcase_field *f = &other->fields[i];
+ subcase_add_always (sc, f->case_index, f->width, f->direction);
+ }
+}
+
+void
+subcase_project (struct subcase *sc, size_t offset)
+{
+ size_t i;
+
+ for (i = 0; i < sc->n_fields; i++)
+ sc->fields[i].case_index = i + offset;
+}
+
+/* Obtains a caseproto for a case described by SC. The caller
+ must not modify or unref the returned case prototype. */
+const struct caseproto *
+subcase_get_proto (const struct subcase *sc_)
+{
+ struct subcase *sc = CONST_CAST (struct subcase *, sc_);
+
+ if (sc->proto == NULL)
+ {
+ size_t i;
+
+ sc->proto = caseproto_create ();
+ for (i = 0; i < sc->n_fields; i++)
+ sc->proto = caseproto_add_width (sc->proto, sc->fields[i].width);
+ }
+ return sc->proto;