+#ifdef HAVE_DATABASE
+Lisp_Object
+char_attribute_system_db_file (Lisp_Object key_type, Lisp_Object attribute,
+ int writing_mode)
+{
+ Lisp_Object db_dir = Vexec_directory;
+
+ if (NILP (db_dir))
+ db_dir = build_string ("../lib-src");
+
+ db_dir = Fexpand_file_name (build_string ("char-db"), db_dir);
+ if (writing_mode && NILP (Ffile_exists_p (db_dir)))
+ Fmake_directory_internal (db_dir);
+
+ db_dir = Fexpand_file_name (Fsymbol_name (key_type), db_dir);
+ if (writing_mode && NILP (Ffile_exists_p (db_dir)))
+ Fmake_directory_internal (db_dir);
+
+ {
+ Lisp_Object attribute_name = Fsymbol_name (attribute);
+ Lisp_Object dest = Qnil, ret;
+ int base = 0;
+ struct gcpro gcpro1, gcpro2;
+ int len = XSTRING_CHAR_LENGTH (attribute_name);
+ int i;
+
+ GCPRO2 (dest, ret);
+ for (i = 0; i < len; i++)
+ {
+ Emchar c = string_char (XSTRING (attribute_name), i);
+
+ if ( (c == '/') || (c == '%') )
+ {
+ char str[4];
+
+ sprintf (str, "%%%02X", c);
+ dest = concat3 (dest,
+ Fsubstring (attribute_name,
+ make_int (base), make_int (i)),
+ build_string (str));
+ base = i + 1;
+ }
+ }
+ ret = Fsubstring (attribute_name, make_int (base), make_int (len));
+ dest = concat2 (dest, ret);
+ UNGCPRO;
+ return Fexpand_file_name (dest, db_dir);
+ }
+#if 0
+ return Fexpand_file_name (Fsymbol_name (attribute), db_dir);
+#endif
+}
+
+DEFUN ("save-char-attribute-table", Fsave_char_attribute_table, 1, 1, 0, /*
+Save values of ATTRIBUTE into database file.
+*/
+ (attribute))
+{
+#ifdef HAVE_DATABASE
+ Lisp_Object table = Fgethash (attribute,
+ Vchar_attribute_hash_table, Qunbound);
+ Lisp_Char_Table *ct;
+ Lisp_Object db_file;
+ Lisp_Object db;
+
+ if (CHAR_TABLEP (table))
+ ct = XCHAR_TABLE (table);
+ else
+ return Qnil;
+
+ db_file = char_attribute_system_db_file (Qsystem_char_id, attribute, 1);
+ db = Fopen_database (db_file, Qnil, Qnil, build_string ("w+"), Qnil);
+ if (!NILP (db))
+ {
+ if (UINT8_BYTE_TABLE_P (ct->table))
+ save_uint8_byte_table (XUINT8_BYTE_TABLE(ct->table), ct, db, 0, 3);
+ else if (UINT16_BYTE_TABLE_P (ct->table))
+ save_uint16_byte_table (XUINT16_BYTE_TABLE(ct->table), ct, db, 0, 3);
+ else if (BYTE_TABLE_P (ct->table))
+ save_byte_table (XBYTE_TABLE(ct->table), ct, db, 0, 3);
+ Fclose_database (db);
+ return Qt;
+ }
+ else
+ return Qnil;
+#else
+ return Qnil;
+#endif
+}
+
+DEFUN ("mount-char-attribute-table", Fmount_char_attribute_table, 1, 1, 0, /*
+Mount database file on char-attribute-table ATTRIBUTE.
+*/
+ (attribute))
+{
+#ifdef HAVE_DATABASE
+ Lisp_Object table = Fgethash (attribute,
+ Vchar_attribute_hash_table, Qunbound);
+
+ if (UNBOUNDP (table))
+ {
+ Lisp_Char_Table *ct;
+
+ table = make_char_id_table (Qunbound);
+ Fputhash (attribute, table, Vchar_attribute_hash_table);
+ XCHAR_TABLE_NAME(table) = attribute;
+ ct = XCHAR_TABLE (table);
+ ct->table = Qunloaded;
+ XCHAR_TABLE_UNLOADED(table) = 1;
+ ct->db = Qnil;
+ return Qt;
+ }
+#endif
+ return Qnil;
+}
+
+DEFUN ("close-char-attribute-table", Fclose_char_attribute_table, 1, 1, 0, /*
+Close database of ATTRIBUTE.
+*/
+ (attribute))
+{
+#ifdef HAVE_DATABASE
+ Lisp_Object table = Fgethash (attribute,
+ Vchar_attribute_hash_table, Qunbound);
+ Lisp_Char_Table *ct;
+
+ if (CHAR_TABLEP (table))
+ ct = XCHAR_TABLE (table);
+ else
+ return Qnil;
+
+ if (!NILP (ct->db))
+ {
+ if (!NILP (Fdatabase_live_p (ct->db)))
+ Fclose_database (ct->db);
+ ct->db = Qnil;
+ }
+#endif
+ return Qnil;
+}
+
+DEFUN ("reset-char-attribute-table", Freset_char_attribute_table, 1, 1, 0, /*
+Reset values of ATTRIBUTE with database file.
+*/
+ (attribute))
+{
+#ifdef HAVE_DATABASE
+ Lisp_Object table = Fgethash (attribute,
+ Vchar_attribute_hash_table, Qunbound);
+ Lisp_Char_Table *ct;
+ Lisp_Object db_file
+ = char_attribute_system_db_file (Qsystem_char_id, attribute, 0);
+
+ if (!NILP (Ffile_exists_p (db_file)))
+ {
+ if (UNBOUNDP (table))
+ {
+ table = make_char_id_table (Qunbound);
+ Fputhash (attribute, table, Vchar_attribute_hash_table);
+ XCHAR_TABLE_NAME(table) = attribute;
+ }
+ ct = XCHAR_TABLE (table);
+ ct->table = Qunloaded;
+ if (!NILP (Fdatabase_live_p (ct->db)))
+ Fclose_database (ct->db);
+ ct->db = Qnil;
+ XCHAR_TABLE_UNLOADED(table) = 1;
+ return Qt;
+ }
+#endif
+ return Qnil;
+}
+
+Lisp_Object
+load_char_attribute_maybe (Lisp_Char_Table* cit, Emchar ch)
+{
+ Lisp_Object attribute = CHAR_TABLE_NAME (cit);
+
+ if (!NILP (attribute))
+ {
+ if (NILP (Fdatabase_live_p (cit->db)))
+ {
+ Lisp_Object db_file
+ = char_attribute_system_db_file (Qsystem_char_id, attribute, 0);
+
+ cit->db = Fopen_database (db_file, Qnil, Qnil,
+ build_string ("r"), Qnil);
+ }
+ if (!NILP (cit->db))
+ {
+ Lisp_Object val
+ = Fget_database (Fprin1_to_string (make_char (ch), Qnil),
+ cit->db, Qunbound);
+ if (!UNBOUNDP (val))
+ val = Fread (val);
+ else
+ val = Qunbound;
+ if (!NILP (Vchar_db_stingy_mode))
+ {
+ Fclose_database (cit->db);
+ cit->db = Qnil;
+ }
+ return val;
+ }
+ }
+ return Qunbound;
+}
+
+Lisp_Char_Table* char_attribute_table_to_load;
+
+Lisp_Object Qload_char_attribute_table_map_function;
+
+DEFUN ("load-char-attribute-table-map-function",
+ Fload_char_attribute_table_map_function, 2, 2, 0, /*
+For internal use. Don't use it.
+*/
+ (key, value))
+{
+ Lisp_Object c = Fread (key);
+ Emchar code = XCHAR (c);
+ Lisp_Object ret = get_char_id_table_0 (char_attribute_table_to_load, code);
+
+ if (EQ (ret, Qunloaded))
+ put_char_id_table_0 (char_attribute_table_to_load, code, Fread (value));
+ return Qnil;
+}
+
+DEFUN ("load-char-attribute-table", Fload_char_attribute_table, 1, 1, 0, /*
+Load values of ATTRIBUTE into database file.
+*/
+ (attribute))
+{
+ Lisp_Object table = Fgethash (attribute,
+ Vchar_attribute_hash_table,
+ Qunbound);
+ if (CHAR_TABLEP (table))
+ {
+ Lisp_Char_Table *ct = XCHAR_TABLE (table);
+
+ if (NILP (Fdatabase_live_p (ct->db)))
+ {
+ Lisp_Object db_file
+ = char_attribute_system_db_file (Qsystem_char_id, attribute, 0);
+
+ ct->db = Fopen_database (db_file, Qnil, Qnil,
+ build_string ("r"), Qnil);
+ }
+ if (!NILP (ct->db))
+ {
+ struct gcpro gcpro1;
+
+ char_attribute_table_to_load = XCHAR_TABLE (table);
+ GCPRO1 (table);
+ Fmap_database (Qload_char_attribute_table_map_function, ct->db);
+ UNGCPRO;
+ Fclose_database (ct->db);
+ ct->db = Qnil;
+ XCHAR_TABLE_UNLOADED(table) = 0;
+ return Qt;
+ }
+ }
+ return Qnil;
+}
+#endif
+