#include #include "machine.h" #include "character.h" #include "error.h" #include "show.h" // extern "C" is needed for dlsym name lookup. Returning std::string from // C-linkage functions is technically non-standard but works correctly on // Linux (Itanium ABI) where C and C++ calling conventions are identical. #if defined(__clang__) #pragma clang diagnostic ignored "-Wreturn-type-c-linkage" #endif extern "C" std::string diacritics_examples([[maybe_unused]] Machine& machine) { if (diacritics.size() != diacritic_symbols_order.size()) { throw Internal_error("Mismatch between diacritics order list and their definitions"); } //std::cout << machine; std::stringstream kt {}; kt << "@table :caption Diacritics (with typical base characters) :cell_hpos c c l |\n" << "@i-Displayed | @i-Written | @i-Name ||\n"; for (char symbol : diacritic_symbols_order) { std::string sym { symbol }; auto [code, name] = diacritics[sym]; std::string letter = diacritic_example_letter[sym]; std::string written = "^" + letter + sym; if (sym == "~") { written = "^" + letter + "^~"; } std::string display = "^" + letter + sym; kt << display << " | @t ^" << written << " @ | " << name << " ||\n"; } kt << "table@"; return kt.str(); } extern "C" std::string extended_latin_examples([[maybe_unused]] Machine& machine) { std::stringstream kt {}; kt << "@table :caption Extended Latin characters and ligatures :cell_hpos c c l |\n" << "@i-Displayed | @i-Written | @i-Name ||\n"; for (const std::string& symbol : extended_latin_symbols) { auto [code, name] = extended_latin[symbol]; std::string coded = "^" + symbol + "^"; std::string file_literal = "^^ #- " + symbol + " #- ^^"; kt << coded << " | @t " << file_literal << " @ | " << name << " ||\n"; } kt << "table@"; return kt.str(); } extern "C" std::string pinyin_examples([[maybe_unused]] Machine& machine) { std::stringstream kt {}; kt << "@table :caption Mandarin pinyin tones (using vowel ``a'') :cell_hpos c c l |\n" << " @i-Displayed | @i-Written | @i-Name ||\n"; for (auto [symbol, codename] : pinyin_tones) { auto [code, name] = codename; std::string literal = "^a" + symbol; kt << literal << " | @t ^" << literal << " @ | " << name << " ||\n"; } kt << "table@"; return kt.str(); } extern "C" std::string unicode_examples([[maybe_unused]] Machine& machine) { std::stringstream kt {}; kt << "\n@s2 Including Unicode in Klammertext files @\n\n" << "To specify a wide variety of different letter forms, the Unicode Standard " << "defines a large set of \"code points\" organized by groups. To include a " << "Unicode character in Klammertext, you surround its hexadecimal number with " << "the \"^^\" character. For example, the Cyrillic captial letter \"I\" is \"И\", " << "included in Klammertext as ^^0418^^.\n\n" << "To search for Unicode characters by their description, see: @nl@\n" << "@link https://www.fileformat.info/info/unicode/char/search.htm @\n\n"; kt << "@table :caption Examples of Chinese characters :cell_hpos c c l |\n" << " Character | Written | Pinyin ||\n"; for (auto chr : dao) { std::string code = "^" + chr[1] + "^"; kt << process_unicode_codepoint(code) << " | " << "^" << code << "^" << " | " << chr[0] << " ||\n"; } kt << "table@\n\n"; kt << "@table :caption Examples of Egyptian hieroglyphs :cell_hpos c c c l |\n" << "Hieroglyph | Written | Sound | Gardiner ||\n"; // The body font carries no hieroglyphs, so the glyph names the // typeface it needs (shipped in fnt/); @document declares and localizes // it. Under txt @typeface passes the text through unchanged. for (auto glyph : ptolemy) { kt << "@typeface noto-sans-egyptian-hieroglyphs :scale 1.5 | " << process_unicode_codepoint("^" + glyph[2] + "^") << " @ | " << "^^" + glyph[2] + "^^ | " << glyph[1] << " | " << glyph[0] << " ||\n"; } kt << "table@\n\n" << "\nIn @link https://en.wikipedia.org/wiki/List_of_Egyptian_hieroglyphs @, " << "the Unicode codepoint in the second column of the \"List of hieroglyphs\" " << "table is the number in the ^^...^^ code used by Klammertext.\n\n"; return kt.str(); } extern "C" std::string argtype_definitions(Machine& machine) { auto argtypes = machine.m_argtypes; std::stringstream kt {}; std::set custom {}; std::map> custom_types {}; kt << "@s2 Types of klammer arguments @\n\n" << "@define :style r | \n"; // Hack to make the "Pattern:" label line up vertically; // there should be a klammer that aligns text at "tab stops". auto name_width = std::string("klammertext").size() + 1; for (const auto& name : argtypes.m_names) { auto argtype = argtypes.m_types.at(name); auto filename = argtype.m_loc.m_filename; if (contains(filename, "argtype_registry")) { std::string fill(name_width - name.size(), '~'); kt << "\n@c " << name << " c@ @t " << fill << " t@ @i Pattern: i@ @c " << argtype.m_symbolic_pattern << " c@ |\n" << capitalize(trim(argtype.m_desc)) << " ||\n"; } else { custom.insert(filename); custom_types[filename].push_back(name); } } kt << "\ndefine@\n\n" << "@vspace .5 @\n@s3 Reusing argtype symbols @\n\n" << "A previously defined type can be included in the definition of a new type " << "by surrounding the name of the existing type in single quotation marks. " << "For example, the @c uint c@ type (unsigned integer) is used to define an integer with a " << "`+' or `-' character before it.\n\n" << "@vspace .5 @\n@s3 Custom argument types @\n\n" << "Other argtypes are defined for special purposes for klammers defined in the following files:\n\n"; kt << "@define :style t |\n"; for (auto [filename, types] : custom_types) { auto type_count = types.size(); int column_count = type_count < 4 ? 1 : int(float(type_count)/3); // auto count = int(float(types.size()) / 3); kt << symbolic_klammertext_filename(filename) << " |\n" << "@columns :style c :n " << column_count << " | " << join(types, " ") << " @ ||\n\n"; } kt << "define@\n\n"; return kt.str(); }