+ if (ISEMPTY(kccgst->keycodes)) {
+ ERROR("keycodes required to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (ISEMPTY(kccgst->compat)) {
+ ERROR("compat map required to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (ISEMPTY(kccgst->types)) {
+ ERROR("types required to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (ISEMPTY(kccgst->symbols)) {
+ ERROR("symbols required to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (!(file = XkbKeymapFileFromComponents(ctx, kccgst))) {
+ ERROR("failed to generate parsed XKB file from components\n");
+ return NULL;
+ }
+
+ return compile_keymap(ctx, file);
+}
+
+_X_EXPORT struct xkb_keymap *
+xkb_map_new_from_string(struct xkb_context *ctx,
+ const char *string,
+ enum xkb_keymap_format format,
+ enum xkb_map_compile_flags flags)
+{
+ XkbFile *file;
+
+ if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
+ ERROR("unsupported keymap format %d\n", format);
+ return NULL;
+ }
+
+ if (!string) {
+ ERROR("no string specified to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (!XKBParseString(ctx, string, "input", &file)) {
+ ERROR("failed to parse input xkb file\n");
+ return NULL;
+ }
+
+ return compile_keymap(ctx, file);
+}
+
+_X_EXPORT struct xkb_keymap *
+xkb_map_new_from_file(struct xkb_context *ctx,
+ FILE *file,
+ enum xkb_keymap_format format,
+ enum xkb_map_compile_flags flags)
+{
+ XkbFile *xkb_file;
+
+ if (format != XKB_KEYMAP_FORMAT_TEXT_V1) {
+ ERROR("unsupported keymap format %d\n", format);
+ return NULL;
+ }
+
+ if (!file) {
+ ERROR("no file specified to generate XKB keymap\n");
+ return NULL;
+ }
+
+ if (!XKBParseFile(ctx, file, "(unknown file)", &xkb_file)) {
+ ERROR("failed to parse input xkb file\n");
+ return NULL;
+ }
+
+ return compile_keymap(ctx, xkb_file);
+}
+
+_X_EXPORT struct xkb_keymap *
+xkb_map_ref(struct xkb_keymap *keymap)
+{
+ keymap->refcnt++;
+ return keymap;
+}
+
+_X_EXPORT void
+xkb_map_unref(struct xkb_keymap *keymap)
+{
+ if (--keymap->refcnt > 0)
+ return;
+
+ XkbcFreeKeyboard(keymap);