Last active
June 10, 2024 18:51
-
-
Save EtiTheSpirit/965f141f5a030cc04c36372d3a625ac1 to your computer and use it in GitHub Desktop.
Enables QMK keyboard firmware to type sitelen pona natively.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// clang-format off | |
// Derived from the AHK script and upgraded by akesi seli San (Xan) for use in QMK keyboard firmware, written in C. | |
// This was written for the ZSA Moonlander but anything using QMK works. I don't know about ZMK. Never used it. | |
// | |
// THIS CODE IS INCOMPLETE; IT IS A SNIPPET FOR YOU TO PUT INTO YOUR OWN FIRMWARE SOURCE. IT WILL NOT BE EASY TO SETUP AND | |
// IS NOT PLUG AND PLAY. SETUP AND C KNOWLEDGE ARE BOTH REQUIRED, DONE SPECIFICALLY FOR YOUR OWN USE CASE. HANDLE WITH CARE. | |
// | |
// Major changes, and how this works: | |
// - This now includes ALL words, including nimisin from Fairfax HD's font. | |
// These words can be toggled via macros, as not all fonts support them. | |
// - Typing in sitelen pona now requires the use of "sitelen pona lock" (for lack of a better name), which needs a dedicated button to swap modes. | |
// YOU MUST ASSIGN THIS BUTTON A KEYCODE ENUM VALUE AND PUT IT ON YOUR KEYBOARD. You are expected to know how to add custom buttons to your keyboard. | |
// Pressing SPACE or ENTER will type the character. | |
// Pressing a modifier key with SPACE (for which modifier, see macros below) can be used to append compound/stacked/scaled characters | |
// Pressing the [ and ] keys (by default) creates a cartouche. Holding shift or alt changes this to a right and left extension respectively. Again, see macros below. | |
// Pressing ESC (by default) CANCELS the current character and turns off sitelen pona lock. Again, again, see macros below. | |
// | |
// - Fairfax HD was the primary focus of this modification and thus several macros later on enable or disable the use of font-specific features. Please handle with care. | |
// NOTE: THIS REQUIRES THE USE OF WINCOMPOSE OR ANOTHER UNICODE INPUT SOLUTION. | |
// FOR MORE INFORMATION, PLEASE READ: https://docs.qmk.fm/features/unicode | |
// TL;DR / EASY WAY: | |
// 1: Install WinCompose at http://wincompose.info/ | |
// 2: Go to config.h and append: #define UNICODE_SELECTED_MODES UC_WINC // (* this may be different if you are running the latest QMK, I am running it old, see https://docs.qmk.fm/features/unicode ) | |
// 3: APPEND THIS CODE TO process_record_user (see https://docs.qmk.fm/understanding_qmk#process-record ) ... | |
/* | |
bool allowContinue = process_record_sitelen_pona(keycode, record); | |
if (!allowContinue) { | |
return false; // Sitelen pona handled this, discard it from the normal keyboard workflow and stop now. | |
} | |
*/ | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
//// REQUIRED SETTINGS | |
// Please fill in the following statement to the keycode that should toggle "sitelen pona lock" | |
#define SITELEN_PONA_TOGGLE_KEYCODE SPEC_NP_EMU | |
// ^ For me, SPEC_NP_EMU is a custom keycode. THIS DEFAULT OPTION WILL NOT WORK FOR YOU. IT IS MINE, FOR MY OWN CODE, IN MY OWN KEYBOARD. | |
// YOU MUST ASSIGN THIS BUTTON A KEYCODE ENUM VALUE AND PUT IT ON YOUR KEYBOARD. You are expected to know how to add custom buttons to your keyboard. | |
// The default code uses this as a toggle in firmware and prevents it from being sent to the system. | |
// THIS MEANS IF YOU ASSIGN IT TO AN ACTUAL USABLE KEY, YOU WILL EFFECTIVELY "LOCK OUT" THAT KEY AND BE UNABLE TO USE IT FOR TYPING. | |
/////////////////////////////////////////////////////////////////////////// | |
//// RECOMMENDED SETTINGS | |
#define SITELEN_PONA_CANCEL_KEYCODE KC_ESC | |
// Optional, set to 0 to disable it. If enabled, pressing this key will "cancel" sitelen pona lock | |
// This is something I added for me mostly because I would compulsively hit esc if I didn't want to type sp any more, or if I made a mistake. | |
// This discards the buffer and turns off the lock. | |
// ALLOW_STACKED_AND_SCALED_COMPOUNDS allows U+200D, U+F1995, and U+F1996 to be typed. These create standard, stacked, and scaled compound glyphs respectively. | |
#define SITELEN_PONA_ALLOW_STACKED_AND_SCALED_COMPOUNDS | |
// Holding any of the provided modifiers and pressing space will type the character (U+200D, U+F1995, U+F1996) needed to create a standard, stacked, or scaled compound. | |
#define SITELEN_PONA_COMPOUND_INTERSECT_KEYCODE KC_LSFT // Standard compounds. | |
#define SITELEN_PONA_COMPOUND_STACKED_KEYCODE KC_LCTRL // Stacked compounds. | |
#define SITELEN_PONA_COMPOUND_SCALED_KEYCODE KC_LALT // Scaled compounds. | |
// "Radicals" are special characters that surround or modify others. In this case, it includes | |
// - Cartouches (the boxes around names) | |
// - Glyph extensions (left and right), particularly useful with words like "pi". They can be grown by typing other sitelen pona, or with spaces. | |
#define SITELEN_PONA_RADICAL_OPEN KC_LBRACKET // Open a radical. Without modifiers, this starts a cartouche. | |
#define SITELEN_PONA_RADICAL_CLOSE KC_RBRACKET // Close a radical. | |
// | |
#define SITELEN_PONA_GLYPH_EXTEND_LEFT_KEYCODE KC_LALT // Holding this causes the above keys to start or stop a left extension. | |
#define SITELEN_PONA_GLYPH_EXTEND_RIGHT_KEYCODE KC_LSFT // Holding this causes the above keys to start or stop a right extension. This is what you use for stuff like pi | |
// ^ These two MUST be modifier keys! | |
/////////////////////////////////////////////////////////////////////////// | |
//// FAIRFAX-SPECIFIC SETTINGS | |
// SETTINGS: | |
#define SITELEN_PONA_ALLOW_UNDEFINED_UCSUR_CODEPOINTS | |
// If DISABLED (commented out), only characters in [F1900−F19FF SITELEN PONA] and [F1C80−F1C9F SITELEN PONA RADICALS] can be used. These are universal. | |
// If DEFINED (not commented out), special characters (primarily nimisin, but some are official now) greater than FFA00 can be typed | |
#define SITELEN_PONA_ALLOW_FAIRFAX_ALTERNATE_SITELEN | |
// REQUIRES: ALLOW_UNDEFINED_UCSUR_CODEPOINTS (if undefined, this does nothing, hence why this is on by default) | |
// If DISABLED (commented out), only characters representing the primary sitelen pona glyph can be used. | |
// If ENABLED (not commented out), alternate characters (often typed by appending a number, i.e. akesi2 or a2) can be used. These are a feature primarily of Fairfax HD. | |
// #define SITELEN_PONA_ALLOW_FAIRFAX_ALT1 | |
// ^ REQUIRES: ALLOW_FAIRFAX_ALTERNATE_SITELEN (if undefined, this does nothing) | |
// This fixes a mistake(?) made by the creator of Fairfax HD where some alternate sitelen (see above) would randomly end with 1 instead of 2, which is very rare. | |
// I assume this is a mistake. Uncommenting this will adjust it so you have to type with a 2+ afterward, like normal. | |
// This affects: olin, epiku, soko | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////////////////////// | |
/////////////////// | |
//// INTERNALS //// | |
#define SITELEN_PONA_COMPOUND_UNICODE "200D" | |
#define SITELEN_PONA_STACKED_COMPOUND_UNICODE "F1995" | |
#define SITELEN_PONA_SCALED_COMPOUND_UNICODE "F1996" | |
#define SITELEN_PONA_INTERPUNCT_UNICODE "F199C" | |
#define SITELEN_PONA_COLON_UNICODE "F199D" | |
#define SITELEN_PONA_CARTOUCHE_START_UNICODE "F1990" | |
#define SITELEN_PONA_CARTOUCHE_END_UNICODE "F1991" | |
#define SITELEN_PONA_LEFT_EXTEND_START_UNICODE "F199A" | |
#define SITELEN_PONA_RIGHT_EXTEND_START_UNICODE "F1997" | |
#define SITELEN_PONA_LEFT_EXTEND_END_UNICODE "F199B" | |
#define SITELEN_PONA_RIGHT_EXTEND_END_UNICODE "F1998" | |
// Handle the defines: | |
// This chain may or may not allow... | |
// FF_EXT "Fairfax Extended" - Used to declare alt variants i.e. a2, a3 | |
// SP_NDEF "sitelen pona, Undefined" - Used to declare values out of UCSUR range like kiki | |
// FF_NDEF "Fairfax, Undefined" - Both of the above simultaneously (only works if both macros are defined simultaneously) | |
#ifdef SITELEN_PONA_ALLOW_UNDEFINED_UCSUR_CODEPOINTS | |
#define SP_NDEF(x, y) {x, y}, | |
#ifdef SITELEN_PONA_ALLOW_FAIRFAX_ALTERNATE_SITELEN | |
#ifdef SITELEN_PONA_ALLOW_FAIRFAX_ALT1 | |
#define _ALLOW_FAIRFAX_ALT1 | |
#endif | |
#define FF_EXT(x, y) {x, y}, | |
#define FF_NDEF(x, y) {x, y}, | |
#else | |
#define FF_EXT(x, y) | |
#define FF_NDEF(x, y) | |
#endif | |
#else | |
#define SP_NDEF(x, y) | |
#define FF_NDEF(x, y) | |
#define FF_EXT(x, y) | |
#endif | |
#define XRT_SEND_UNICODE(s) unicode_input_start(); SEND_STRING(s); unicode_input_finish() | |
#define SITELEN_PONA_LARGEST_TP_WORD_SIZE 48 | |
struct TokiPonaWordBinding { | |
char word[SITELEN_PONA_LARGEST_TP_WORD_SIZE]; | |
const char* uni; | |
} TokiPonaWordBinding; | |
char sitelenPonaCurrentBuffer[SITELEN_PONA_LARGEST_TP_WORD_SIZE + 1]; | |
int sitelenPonaCurrentBufferPos = 0; | |
#ifndef _XAN_PERSONAL_ALREADY_DEFINED_SITELEN_PONA_LOCK | |
bool sitelenPonaLock = false; | |
#endif | |
const struct TokiPonaWordBinding sitelenPonaLookup[] = { | |
{"a", "F1900"}, | |
FF_EXT ("a2", "FFB11") | |
FF_EXT ("a3", "FFD60") | |
FF_EXT ("a4", "FFD61") | |
FF_EXT ("a5", "FFD62") | |
SP_NDEF ("aka", "FFB3A") | |
{"akesi", "F1901"}, | |
FF_EXT ("akesi2", "FFD63") | |
SP_NDEF ("akesiv", "FFAFF") | |
FF_NDEF ("akesiv2", "FFD64") | |
SP_NDEF ("ako", "FFB73") | |
FF_NDEF ("ako2", "FFB2B") | |
SP_NDEF ("aku", "FFD87") | |
{"ala", "F1902"}, | |
{"ali", "F1904"}, | |
{"alasa", "F1903"}, | |
{"ale", "F1904"}, | |
SP_NDEF ("alente", "FFD80") | |
SP_NDEF ("alu", "FFB40") | |
SP_NDEF ("ana", "FFDB1") | |
SP_NDEF ("ani", "FFD88") | |
{"anpa", "F1905"}, | |
SP_NDEF ("anta", "FFD89") | |
{"ante", "F1906"}, | |
SP_NDEF ("antikontitutonelema", "FFDCE") | |
#ifdef _ALLOW_FAIRFAX_ALT1 | |
FF_NDEF ("antikontitutonelema1", "FFDCF") | |
#else | |
FF_NDEF ("antikontitutonelema2", "FFDCF") | |
#endif | |
{"anu", "F1907"}, | |
{"apeja", "F19A1"}, | |
SP_NDEF ("apelo", "FFD8A") | |
SP_NDEF ("api", "FFDBB") | |
FF_NDEF ("api2", "FFDBC") | |
FF_NDEF ("api3", "FFDBD") | |
FF_NDEF ("api4", "FFDBA") | |
SP_NDEF ("awase", "FFB41") | |
{"awen", "F1908"}, | |
{"e", "F1909"}, | |
SP_NDEF ("eki", "FFB3A") | |
SP_NDEF ("elen", "FFD8B") | |
SP_NDEF ("eliki", "FFDAC") | |
{"en", "F190A"}, | |
SP_NDEF ("ene", "FFDB2") | |
SP_NDEF ("eni", "FFDB2") | |
SP_NDEF ("enepi", "FFDAD") | |
SP_NDEF ("enko", "FFB43") | |
FF_NDEF ("enko2", "FFB44") | |
FF_NDEF ("enko3", "FFB45") | |
{"epiku", "F1983"}, | |
SP_NDEF ("epikule", "FFB8B") | |
#ifdef _ALLOW_FAIRFAX_ALT1 | |
FF_EXT ("epiku1", "FFAAB") | |
#else | |
FF_EXT ("epiku2", "FFAAB") | |
#endif | |
{"esun", "F190B"}, | |
SP_NDEF ("ete", "FFACC") | |
FF_NDEF ("ete2", "FFACD") | |
SP_NDEF ("ewe", "FFAD9") | |
SP_NDEF ("i", "FFB46") | |
{"ijo", "F190C"}, | |
{"ike", "F190D"}, | |
SP_NDEF ("iki", "FFB47") | |
FF_NDEF ("iki2", "FFB0B") | |
{"ilo", "F190E"}, | |
{"insa", "F190F"}, | |
SP_NDEF ("ipi", "FFB48") | |
FF_NDEF ("ipi2", "FFB0D") | |
SP_NDEF ("itomi", "FFB49") | |
SP_NDEF ("iseki", "FFD8C") | |
SP_NDEF ("isipin", "FFAC0") | |
SP_NDEF ("ja", "FFD2F") | |
{"jaki", "F1910"}, | |
SP_NDEF ("jaku", "FFB4D") | |
SP_NDEF ("jalan", "FFAD1") | |
SP_NDEF ("jami", "FFB31") | |
SP_NDEF ("jans", "FFB8E") | |
{"jan", "F1911"}, | |
{"jasima", "F197F"}, | |
SP_NDEF ("je", "FFB4E") | |
FF_NDEF ("je2", "FFB29") | |
{"jelo", "F1912"}, | |
SP_NDEF ("jew", "FFB8F") | |
{"jo", "F1913"}, | |
SP_NDEF ("jonke", "FFB4F") | |
SP_NDEF ("jule", "FFD81") | |
SP_NDEF ("jume", "FFB74") | |
{"kala", "F1914"}, | |
FF_EXT ("kala2", "FFAA0") | |
{"kalama", "F1915"}, | |
SP_NDEF ("kalamarr", "FFAFE") // AGREED MATEY | |
SP_NDEF ("kalamawala", "FFADA") | |
SP_NDEF ("kalapisituwi", "FFD8D") | |
SP_NDEF ("kalijopilale", "FFBA0") | |
{"kama", "F1916"}, | |
SP_NDEF ("kan", "FFACF") | |
SP_NDEF ("kana", "FFD8E") | |
SP_NDEF ("kankuli", "FFDE1") | |
SP_NDEF ("kapa", "FFB51") | |
SP_NDEF ("kapesi", "FFAC1") | |
FF_NDEF ("kapesi2", "FFAC2") | |
{"kasi", "F1917"}, | |
SP_NDEF ("ke", "FFADB") | |
FF_NDEF ("ke2", "FFB24") | |
{"ken", "F1918"}, | |
SP_NDEF ("kepa", "FFE50") | |
{"kepeken", "F1919"}, | |
{"kepen", "F1919"}, // Feels wrong to include here but it's defined so... | |
SP_NDEF ("kese", "FFADF") | |
SP_NDEF ("ki", "FFB55") | |
SP_NDEF ("kijosin", "FFBA1") | |
SP_NDEF ("kiki", "FFAC3") | |
FF_NDEF ("kiki2", "FFD6D") | |
FF_NDEF ("kiki3", "FFD6E") | |
FF_NDEF ("kiki4", "FFD6F") | |
{"kili", "F191A"}, | |
{"kijetesantakalu", "F1980"}, | |
FF_EXT ("kijetesantakalu2", "FFDC8") | |
SP_NDEF ("kikolo", "FFD8F") | |
{"kin", "F1979"}, | |
FF_EXT ("kin2", "FFB15") | |
SP_NDEF ("kikulo", "FFD90") | |
{"kipisi", "F197B"}, | |
SP_NDEF ("kisa", "FFB57") | |
{"kiwen", "F191B"}, | |
{"ko", "F191C"}, | |
{"kokosila", "F1984"}, | |
FF_EXT ("kokosila2", "FFAAE") | |
SP_NDEF ("kolo", "FFDBE") | |
{"kon", "F191D"}, | |
SP_NDEF ("koni", "FFD92") | |
SP_NDEF ("kokoliko", "FFD91") | |
SP_NDEF ("konsi", "FFB75") | |
SP_NDEF ("konwe", "FFB58") | |
SP_NDEF ("kosan", "FFB59") | |
SP_NDEF ("kosikosa", "FFD93") | |
{"ku", "F1988"}, | |
FF_EXT ("ku2", "FFD76") | |
FF_EXT ("ku3", "FFD77") | |
FF_EXT ("ku4", "FFD78") | |
FF_EXT ("ku5", "FFD79") | |
FF_EXT ("ku6", "FFD7A") | |
FF_EXT ("ku7", "FFD7B") | |
SP_NDEF ("kulaso", "FFDCA") | |
{"kule", "F191E"}, | |
SP_NDEF ("kulepiku", "FFB8A") | |
SP_NDEF ("kulijo", "FFAE1") | |
FF_NDEF ("kulijo2", "FFDBF") | |
SP_NDEF ("kulu", "FFB5D") | |
{"kulupu", "F191F"}, | |
SP_NDEF ("kuntu", "FFAD0") | |
{"kute", "F1920"}, | |
SP_NDEF ("kutopoma", "FFB77") | |
{"la", "F1921"}, | |
{"lanpan", "F1985"}, | |
FF_EXT ("lanpan2", "FFAB0") | |
FF_EXT ("lanpan3", "FFAB1") | |
SP_NDEF ("lansan", "FFBAB") | |
SP_NDEF ("lato", "FFDB4") | |
{"lape", "F1922"}, | |
{"laso", "F1923"}, | |
{"lawa", "F1924"}, | |
{"leko", "F197C"}, | |
{"len", "F1925"}, | |
{"lete", "F1926"}, | |
{"li", "F1927"}, | |
SP_NDEF ("lijokuku", "FFB78") | |
FF_NDEF ("lijokuku2", "FFB79") | |
SP_NDEF ("likujo", "FFAE2") | |
{"lili", "F1928"}, | |
{"linja", "F1929"}, | |
SP_NDEF ("linluwi", "FFAC4") | |
FF_NDEF ("linluwi2", "FFBA5") | |
FF_NDEF ("linluwi3", "FFD6B") | |
FF_NDEF ("linluwi4", "FFD6C") | |
{"lipu", "F192A"}, | |
SP_NDEF ("lisana", "FFDC0") | |
FF_NDEF ("lisana2", "FFDC1") | |
{"loje", "F192B"}, | |
SP_NDEF ("lo", "FFB7A") | |
SP_NDEF ("loka", "FFAD1") | |
SP_NDEF ("lokon", "FFB5E") | |
{"lon", "F192C"}, | |
SP_NDEF ("lu", "FFB7A") | |
{"luka", "F192D"}, | |
{"lukin", "F192E"}, | |
{"lupa", "F192F"}, | |
{"ma", "F1930"}, | |
{"mama", "F1931"}, | |
SP_NDEF ("mamasi", "FFBA9") | |
SP_NDEF ("mamasina", "FFBA9") | |
{"majuna", "F19A2"}, | |
FF_EXT ("majuna2", "FFAB3") | |
{"mani", "F1932"}, | |
SP_NDEF ("masalo", "FFD94") | |
SP_NDEF ("masu", "FFDB3") | |
SP_NDEF ("masenta", "FFDCD") | |
SP_NDEF ("matula", "FFD95") | |
SP_NDEF ("me", "FFB7C") | |
{"meli", "F1933"}, | |
FF_EXT ("meli2", "FFAA1") | |
FF_EXT ("meli3", "FFD19") | |
SP_NDEF ("melome", "FFB32") | |
{"meso", "F1982"}, | |
FF_EXT ("meso2", "FFAAA") | |
{"mi", "F1934"}, | |
FF_EXT ("mi2", "FFB05") | |
SP_NDEF ("mijomi", "FFB36") | |
SP_NDEF ("miko", "FFE51") | |
FF_NDEF ("miko2", "FFE52") | |
SP_NDEF ("misa", "FFAD2") | |
FF_NDEF ("misa2", "FFAD3") | |
FF_NDEF ("misa3", "FFAD4") | |
FF_NDEF ("misa4", "FFAD5") | |
FF_NDEF ("misa5", "FFAD6") | |
FF_NDEF ("misa6", "FFAD7") | |
{"misikeke", "F1987"}, | |
FF_EXT ("misikeke2", "FFD6A") | |
{"mije", "F1935"}, | |
FF_EXT ("mije2", "FFAA2") | |
FF_EXT ("mije3", "FFD18") | |
{"moku", "F1936"}, | |
{"moli", "F1937"}, | |
FF_EXT ("moli2", "FFD68") | |
SP_NDEF ("molusa", "FFB5F") | |
{"monsi", "F1938"}, | |
{"monsuta", "F197D"}, | |
{"mu", "F1939"}, | |
FF_EXT ("mu2", "F1939") | |
SP_NDEF ("mulapisu", "FFAC8") | |
{"mun", "F193A"}, | |
{"musi", "F193B"}, | |
FF_EXT ("musi2", "FFD2E") | |
{"mute", "F193C"}, | |
FF_EXT ("mute2", "FFD69") | |
SP_NDEF ("nalanja", "FFDB6") | |
#ifdef _ALLOW_FAIRFAX_ALT1 | |
FF_NDEF ("nalanja1", "FFD82") | |
#else | |
FF_NDEF ("nalanja2", "FFD82") | |
#endif | |
{"namako", "F1978"}, | |
FF_EXT ("namako2", "FFAA8") | |
{"nanpa", "F193D"}, | |
{"nasin", "F193F"}, | |
{"nasa", "F193E"}, | |
SP_NDEF ("natu", "FFB3A") | |
SP_NDEF ("neja", "FFAE3") | |
SP_NDEF ("nele", "FFB7D") | |
{"nena", "F1940"}, | |
{"n", "F1986"}, | |
FF_EXT ("n2", "FFB1A") | |
{"ni", "F1941"}, | |
FF_EXT ("ni2", "FFB02") | |
FF_EXT ("ni3", "FFB01") | |
FF_EXT ("ni4", "FFB00") | |
FF_EXT ("ni5", "FFD72") | |
FF_EXT ("ni6", "FFD71") | |
FF_EXT ("ni7", "FFD70") | |
FF_EXT ("ni8", "FFD73") | |
{"nimi", "F1942"}, | |
SP_NDEF ("nimisin", "FFD96") | |
SP_NDEF ("nja", "FFB60") | |
{"noka", "F1943"}, | |
SP_NDEF ("nowi", "FFD97") | |
SP_NDEF ("nu", "FFB7E") | |
SP_NDEF ("nuwa", "FFB7F") | |
{"o", "F1944"}, | |
FF_EXT ("o2", "FFB13") | |
SP_NDEF ("ojuta", "FFD83") // We can't add this, otherwise steve jobs will die! | |
SP_NDEF ("oke", "FFAE4") | |
SP_NDEF ("okepuma", "FFB61") | |
SP_NDEF ("oki", "FFB84") | |
{"oko", "F197A"}, | |
SP_NDEF ("olala", "FFD98") | |
{"olin", "F1945"}, | |
#ifdef _ALLOW_FAIRFAX_ALT1 | |
FF_EXT ("olin1", "FFD75") | |
FF_EXT ("olin2", "FFAA3") | |
#else | |
FF_EXT ("olin2", "FFD75") | |
FF_EXT ("olin3", "FFAA3") | |
#endif | |
SP_NDEF ("omekalike", "FFD84") | |
SP_NDEF ("omekapo", "FFB3B") | |
SP_NDEF ("omen", "FFB62") | |
{"ona", "F1946"}, | |
FF_EXT ("ona2", "FFB09") | |
SP_NDEF ("oni", "FFB63") | |
FF_NDEF ("oni2", "FFB64") | |
SP_NDEF ("opasan", "FFD99") | |
{"open", "F1947"}, | |
SP_NDEF ("owe", "FFB65") | |
SP_NDEF ("pa", "FFB66") | |
SP_NDEF ("pakola", "FFD9A") | |
FF_NDEF ("pakola2", "FFD9B") | |
{"pan", "F194B"}, | |
SP_NDEF ("panke", "FFD9C") | |
{"pakala", "F1948"}, | |
{"pake", "F19A0"}, | |
{"palisa", "F194A"}, | |
{"pali", "F1949"}, | |
{"pana", "F194C"}, | |
SP_NDEF ("pasila", "FFB67") | |
SP_NDEF ("pata", "FFAE5") | |
SP_NDEF ("penpo", "FFDC9") | |
SP_NDEF ("peta", "FFB69") | |
SP_NDEF ("peto", "FFAE6") | |
SP_NDEF ("pika", "FFB6A") | |
FF_NDEF ("pika2", "FFD9D") | |
{"pilin", "F194E"}, | |
{"pimeja", "F194F"}, | |
SP_NDEF ("pingo", "FFAFD") // ? | |
{"pini", "F1950"}, | |
{"pipi", "F1951"}, | |
SP_NDEF ("pipo", "FFB6B") | |
SP_NDEF ("pipolo", "FFD9E") | |
SP_NDEF ("po", "FFAE7") | |
{"poka", "F1952"}, | |
{"poki", "F1953"}, | |
{"pona", "F1954"}, | |
SP_NDEF ("polinpin", "FFAE8") | |
SP_NDEF ("pomotolo", "FFAE9") | |
SP_NDEF ("poni", "FFB80") // It is registered as "poni1" but I think that is a mistake too because there is no "poni" | |
SP_NDEF ("poni1", "FFB80") | |
FF_NDEF ("poni2", "FFD85") | |
FF_NDEF ("poni3", "FFDC2") | |
FF_NDEF ("poni4", "FFDC3") | |
FF_NDEF ("poni5", "FFDC4") | |
FF_NDEF ("poni6", "FFDC5") | |
FF_NDEF ("poni7", "FFDC6") | |
FF_NDEF ("poni8", "FFDC7") | |
{"powe", "F19A3"}, | |
{"pi", "F194D"}, | |
{"pu", "F1955"}, | |
SP_NDEF ("pulaso", "FFDCC") | |
SP_NDEF ("puwa", "FFB3C") | |
SP_NDEF ("saja", "FFDB0") | |
{"sama", "F1956"}, | |
SP_NDEF ("samu", "FFAC9") | |
SP_NDEF ("san", "FFAEB") | |
SP_NDEF ("sapelipope", "FFD9F") | |
{"seli", "F1957"}, | |
{"selo", "F1958"}, | |
{"seme", "F1959"}, | |
{"sewi", "F195A"}, | |
FF_EXT ("sewi2", "FFAA4") | |
{"sijelo", "F195B"}, | |
SP_NDEF ("sikako", "FFDA0") | |
{"sike", "F195C"}, | |
SP_NDEF ("sikomo", "FFB6C") | |
SP_NDEF ("silapa", "FFDA1") | |
FF_NDEF ("silapa1", "FFDF0") | |
FF_NDEF ("silapa2", "FFDF1") | |
FF_NDEF ("silapa3", "FFDF2") | |
{"sin", "F195D"}, | |
{"sina", "F195E"}, | |
FF_EXT ("sina2", "FFB07") | |
{"sinpin", "F195F"}, | |
SP_NDEF ("sipi", "FFB81") | |
SP_NDEF ("sipije", "FFDA2") | |
SP_NDEF ("sisi", "FFDA3") | |
{"sitelen", "F1960"}, | |
SP_NDEF ("siwala", "FFDA4") | |
SP_NDEF ("slape", "FFB8D") | |
SP_NDEF ("snoweli", "FFDA5") | |
{"soko", "F1981"}, | |
#ifdef _ALLOW_FAIRFAX_ALT1 | |
FF_EXT ("soko1", "FFD65") | |
FF_EXT ("soko2", "FFD66") | |
#else | |
FF_EXT ("soko2", "FFD65") | |
FF_EXT ("soko3", "FFD66") | |
#endif | |
{"sona", "F1961"}, | |
SP_NDEF ("soni", "FFDA6") | |
SP_NDEF ("soto", "FFAEC") | |
{"soweli", "F1962"}, | |
SP_NDEF ("sowoli", "FFB86") | |
SP_NDEF ("su", "FFB2F") | |
FF_NDEF ("su2", "FFB3D") | |
SP_NDEF ("sulaso", "FFDCB") | |
{"suli", "F1963"}, | |
{"suno", "F1964"}, | |
{"supa", "F1965"}, | |
SP_NDEF ("sutopatikuna", "FFAFB") | |
{"suwi", "F1966"}, | |
SP_NDEF ("ta", "FFDA7") | |
FF_NDEF ("ta2", "FFE53") | |
SP_NDEF ("taki", "FFAED") | |
FF_NDEF ("taki2", "FFAEE") | |
{"tan", "F1967"}, | |
{"taso", "F1968"}, | |
SP_NDEF ("tasun", "FFDA8") | |
#ifdef _ALLOW_FAIRFAX_ALT1 | |
FF_NDEF ("tasun1", "FFDF5") | |
FF_NDEF ("tasun2", "FFDF6") | |
FF_NDEF ("tasun3", "FFDF7") | |
#else | |
FF_NDEF ("tasun2", "FFDF5") | |
FF_NDEF ("tasun3", "FFDF6") | |
FF_NDEF ("tasun4", "FFDF7") | |
#endif | |
SP_NDEF ("taasun", "FFDF8") | |
SP_NDEF ("taaasun", "FFDF9") | |
{"tawa", "F1969"}, | |
SP_NDEF ("te", "FFAF0") | |
SP_NDEF ("teje", "FFAEF") | |
SP_NDEF ("teken", "FFDB9") | |
{"telo", "F196A"}, | |
{"ten", "F196B"}, | |
FF_NDEF ("ten2", "FFBAD") | |
{"tenpo", "F196B"}, | |
SP_NDEF ("to", "FFAF1") | |
SP_NDEF ("tokana", "FFB70") | |
FF_NDEF ("tokana2", "FFD9A") | |
FF_NDEF ("tokana3", "FFDAA") | |
{"toki", "F196C"}, | |
{"tomo", "F196D"}, | |
SP_NDEF ("tona", "FFBAE") | |
{"tonsi", "F197E"}, | |
FF_EXT ("tonsi2", "FFD08") | |
FF_EXT ("tonsi3", "FFD1A") | |
FF_EXT ("tonsi4", "FFD1B") | |
SP_NDEF ("topo", "FFDB5") | |
{"tu", "F196E"}, | |
SP_NDEF ("tuli", "FFAEB") | |
SP_NDEF ("tuwa", "FFE54") | |
SP_NDEF ("umesu", "FFAF2") | |
FF_NDEF ("umesu2", "FFDB8") | |
// https://youtu.be/lGJBUauU-CE?t=141 | |
// o lukin a! | |
// a | |
// u n p a | |
{"unpa", "F196F"}, | |
SP_NDEF ("unu", "FFACA") | |
SP_NDEF ("usawi", "FFAF6") | |
{"uta", "F1970"}, | |
FF_EXT ("uta2", "FFAA5") | |
{"utala", "F1971"}, | |
SP_NDEF ("wa", "FFACB") | |
FF_NDEF ("wa2", "FFB1F") | |
SP_NDEF ("waken", "FFBAA") | |
SP_NDEF ("waleja", "FFAD8") | |
{"walo", "F1972"}, | |
{"wan", "F1973"}, | |
{"waso", "F1974"}, | |
SP_NDEF ("wasoweli", "FFAF7") | |
{"wawa", "F1975"}, | |
SP_NDEF ("wawajete", "FFB71") | |
SP_NDEF ("we", "FFDB7") | |
{"weka", "F1976"}, | |
SP_NDEF ("wekama", "FFB3E") | |
SP_NDEF ("wi", "FFB82") | |
FF_NDEF ("wi2", "FFB0F") | |
SP_NDEF ("wiju", "FFDAF") | |
SP_NDEF ("wiki", "FFBAC") | |
{"wile", "F1977"}, | |
FF_EXT ("wile2", "FFAA6") | |
SP_NDEF ("wiwi", "FFDAB") | |
SP_NDEF ("wowujiti", "FFD86") | |
SP_NDEF ("wuwojiti", "FFD86") | |
// src: https://www.kreativekorp.com/software/fonts/fairfaxponahd/ | |
// I guess y got manifested into existence. | |
SP_NDEF ("yupekosi", "FFAFC") | |
SP_NDEF ("yutu", "FFB8C") | |
}; | |
// String equality on custom string pointers. | |
static int strEqu(const char* a, const char* b, int maxLength) { | |
for (int i = 0; i <= maxLength; i++) { | |
char aNow = a[i]; | |
char bNow = b[i]; | |
if (aNow != bNow) { | |
return 0; // Break immediately. | |
} else if (aNow == 0 && bNow == 0) { | |
return 1; // Only if both are zero do we ever return true. | |
} | |
} | |
return 0; // Otherwise it's not right. | |
} | |
// Returns the hex unicode string for the currently typed toki pona word stored in buffer, | |
// or 0 if no such character exists. | |
static const char* getUnicodeOfCurrentSitelen(void) { | |
if (sitelenPonaCurrentBufferPos == 0) return 0; | |
const int length = sizeof(sitelenPonaLookup) / sizeof(TokiPonaWordBinding); | |
for (int i = 0; i < length; ++i) { | |
struct TokiPonaWordBinding word = sitelenPonaLookup[i]; | |
if (strEqu(word.word, sitelenPonaCurrentBuffer, sitelenPonaCurrentBufferPos)) { | |
return word.uni; | |
} | |
} | |
return 0; | |
} | |
// Pushes a character into the sitelen pona buffer. | |
static void pushSitelenPona(char kc) { | |
if (sitelenPonaCurrentBufferPos < SITELEN_PONA_LARGEST_TP_WORD_SIZE) { | |
sitelenPonaCurrentBuffer[sitelenPonaCurrentBufferPos] = kc; | |
sitelenPonaCurrentBufferPos++; | |
} | |
} | |
// Clears the sitelen pona buffer, which tracks the toki pona word being typed. | |
static void clearSitelenPonaBuffer(void) { | |
for (int i = 0; i <= SITELEN_PONA_LARGEST_TP_WORD_SIZE; ++i) { | |
// Note above: <= not < | |
sitelenPonaCurrentBuffer[i] = '\0'; | |
} | |
sitelenPonaCurrentBufferPos = 0; | |
} | |
// Checks the toki pona buffer, and if a word is recognized, types it. | |
static void sendSitelenPonaIfKnown(void) { | |
sitelenPonaCurrentBuffer[SITELEN_PONA_LARGEST_TP_WORD_SIZE] = '\0'; // Ensure null ending. | |
const char* uni = getUnicodeOfCurrentSitelen(); | |
if (uni) { | |
XRT_SEND_UNICODE(uni); | |
} | |
else { | |
// If it was unrecognized, just send the actual string that was buffered. | |
// This is part of why the null ending is enforced. | |
SEND_STRING((char*)(&sitelenPonaCurrentBuffer)); | |
} | |
clearSitelenPonaBuffer(); | |
} | |
static bool process_record_sitelen_pona(uint16_t keycode, keyrecord_t* record) { | |
int modState = get_mods(); | |
bool compound = false; | |
bool stacked = false; | |
bool scaled = false; | |
// bool shift = modState & (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)); | |
#ifdef SITELEN_PONA_ALLOW_STACKED_AND_SCALED_COMPOUNDS | |
#ifdef SITELEN_PONA_COMPOUND_INTERSECT_KEYCODE | |
compound = modState & MOD_BIT(SITELEN_PONA_COMPOUND_INTERSECT_KEYCODE); | |
#endif | |
#ifdef SITELEN_PONA_COMPOUND_STACKED_KEYCODE | |
stacked = modState & MOD_BIT(SITELEN_PONA_COMPOUND_STACKED_KEYCODE); | |
#endif | |
#ifdef SITELEN_PONA_COMPOUND_SCALED_KEYCODE | |
scaled = modState & MOD_BIT(SITELEN_PONA_COMPOUND_SCALED_KEYCODE); | |
#endif | |
#endif | |
bool extendLeft = false; | |
bool extendRight = false; | |
#ifdef SITELEN_PONA_GLYPH_EXTEND_LEFT_KEYCODE | |
extendLeft = modState & MOD_BIT(SITELEN_PONA_GLYPH_EXTEND_LEFT_KEYCODE); | |
#endif | |
#ifdef SITELEN_PONA_GLYPH_EXTEND_RIGHT_KEYCODE | |
extendRight = modState & MOD_BIT(SITELEN_PONA_GLYPH_EXTEND_RIGHT_KEYCODE); | |
#endif | |
bool isPressed = (bool)(record->event.pressed); | |
if (keycode == SITELEN_PONA_TOGGLE_KEYCODE && isPressed) { | |
sendSitelenPonaIfKnown(); | |
sitelenPonaLock = !sitelenPonaLock; | |
return false; | |
} | |
if (sitelenPonaLock && isPressed) { | |
switch (keycode) { | |
case KC_ENTER: | |
if (sitelenPonaCurrentBufferPos != 0) { | |
sendSitelenPonaIfKnown(); | |
} | |
return true; | |
case KC_SPACE: | |
// Cause spacebar to type TP words. | |
if (sitelenPonaCurrentBufferPos != 0) { | |
sendSitelenPonaIfKnown(); | |
if (!compound && !stacked && !scaled) return false; | |
} | |
if (compound || stacked || scaled) { | |
if (compound) { | |
XRT_SEND_UNICODE(SITELEN_PONA_COMPOUND_UNICODE); | |
} else if (stacked) { | |
XRT_SEND_UNICODE(SITELEN_PONA_STACKED_COMPOUND_UNICODE); | |
} else if (scaled) { | |
XRT_SEND_UNICODE(SITELEN_PONA_SCALED_COMPOUND_UNICODE); | |
} | |
return false; | |
} | |
return true; | |
case KC_SCOLON: | |
sendSitelenPonaIfKnown(); | |
XRT_SEND_UNICODE(SITELEN_PONA_COLON_UNICODE); | |
return false; | |
case KC_DOT: | |
sendSitelenPonaIfKnown(); | |
XRT_SEND_UNICODE(SITELEN_PONA_INTERPUNCT_UNICODE); | |
return false; | |
case SITELEN_PONA_RADICAL_OPEN: | |
sendSitelenPonaIfKnown(); | |
if ((extendLeft && extendRight) || (!extendLeft && !extendRight)) { | |
XRT_SEND_UNICODE(SITELEN_PONA_CARTOUCHE_START_UNICODE); | |
} else if (extendLeft) { | |
XRT_SEND_UNICODE(SITELEN_PONA_LEFT_EXTEND_START_UNICODE); | |
} else if (extendRight) { | |
XRT_SEND_UNICODE(SITELEN_PONA_RIGHT_EXTEND_START_UNICODE); | |
} | |
return false; | |
case SITELEN_PONA_RADICAL_CLOSE: | |
sendSitelenPonaIfKnown(); | |
if ((extendLeft && extendRight) || (!extendLeft && !extendRight)) { | |
XRT_SEND_UNICODE(SITELEN_PONA_CARTOUCHE_END_UNICODE); | |
} else if (extendLeft) { | |
XRT_SEND_UNICODE(SITELEN_PONA_LEFT_EXTEND_END_UNICODE); | |
} else if (extendRight) { | |
XRT_SEND_UNICODE(SITELEN_PONA_RIGHT_EXTEND_END_UNICODE); | |
} | |
return false; | |
case SITELEN_PONA_CANCEL_KEYCODE: | |
clearSitelenPonaBuffer(); | |
sitelenPonaLock = false; | |
return false; | |
} | |
const int ASCII_OFFSET = 97 - KC_A; // 93 + 4 = 97 | |
const int NUMBER_OFFSET_RAW = 0x31; // '1' is 0x31 | |
bool isAZ = keycode >= KC_A && keycode <= KC_Z; | |
bool isNum = keycode >= KC_1 && keycode <= KC_0; | |
if (isAZ || isNum) { | |
char c; | |
if (isAZ) { | |
c = (char)(keycode + ASCII_OFFSET); | |
} else if (isNum) { | |
if (keycode == KC_0) { | |
c = '0'; // hardcode this because it's reverse order in ASCII (0 is before 1, rather than 1234567890) | |
} else { | |
c = (char)(keycode - KC_1 + NUMBER_OFFSET_RAW); | |
} | |
} | |
//if (isAZ && shift) { | |
// c -= 0x20; // Capitalize | |
//} | |
pushSitelenPona(c); | |
return false; | |
} | |
} | |
return true; | |
} | |
// clang-format on |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment