From ac92da96856603d450e39fa536f287bcf67c0fd7 Mon Sep 17 00:00:00 2001 From: dam Date: Fri, 15 Mar 2024 01:46:01 +0000 Subject: Improved key map. --- modules/TUI/key_map.jai | 501 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 501 insertions(+) create mode 100644 modules/TUI/key_map.jai (limited to 'modules/TUI/key_map.jai') diff --git a/modules/TUI/key_map.jai b/modules/TUI/key_map.jai new file mode 100644 index 0000000..42acabf --- /dev/null +++ b/modules/TUI/key_map.jai @@ -0,0 +1,501 @@ +#import "Hash_Table"; + +key_map: Table(string, Key); + +setup_key_map :: () { + /* + This table was created/tested using the following terminals: + - g: gnome (terminal) + - i: kitty + - k: konsole + - l: linux (console) + - x: xterm + + To signal modifier keys, a letter is appended after a + (plus sign): + "#f1" -> F1 + "#f1+$" -> F1 + Shift + "#f1+a" -> F1 + Alt + "#f1+A" -> F1 + Shift + Alt + "#f1+c" -> F1 + Ctrl + "#f1+C" -> F1 + Shift + Ctrl + "#f1+w" -> F1 + Alt + Ctrl + "#f1+W" -> F1 + Shift + Alt + Ctrl + "#f1+s" -> F1 + Super + "#f1+S" -> F1 + Shift + Super + "#f1+x" -> F1 + Alt + Super + "#f1+X" -> F1 + Shift + Alt + Super + "#f1+y" -> F1 + Ctrl + Super + "#f1+Y" -> F1 + Shift + Ctrl + Super + "#f1+z" -> F1 + Alt + Ctrl + Super + "#f1+Z" -> F1 + Shift + Alt + Ctrl + Super + */ + + // Up // g i k l x + // table_set(*key_map, "\e[A", to_key("#up")); // + + + + + + table_set(*key_map, "\e[1;1A", to_key("#up")); // + table_set(*key_map, "\e[1;2A", to_key("#up+$")); // + + + + + table_set(*key_map, "\e[1;3A", to_key("#up+a")); // + + + + + table_set(*key_map, "\e[1;4A", to_key("#up+A")); // + + + + + table_set(*key_map, "\e[1;5A", to_key("#up+c")); // + + + + + table_set(*key_map, "\e[1;6A", to_key("#up+C")); // + + + + + table_set(*key_map, "\e[1;7A", to_key("#up+w")); // + + + + + table_set(*key_map, "\e[1;8A", to_key("#up+W")); // + + + + + table_set(*key_map, "\e[1;9A", to_key("#up+s")); // + + table_set(*key_map, "\e[1;10A", to_key("#up+S")); // + + table_set(*key_map, "\e[1;11A", to_key("#up+x")); // + + table_set(*key_map, "\e[1;12A", to_key("#up+X")); // + + table_set(*key_map, "\e[1;13A", to_key("#up+y")); // + + table_set(*key_map, "\e[1;14A", to_key("#up+Y")); // + + table_set(*key_map, "\e[1;15A", to_key("#up+z")); // + + table_set(*key_map, "\e[1;16A", to_key("#up+Z")); // + + + // Down // g i k l x + table_set(*key_map, "\e[B", to_key("#down")); // + + + + + + table_set(*key_map, "\e[1;1B", to_key("#down")); // + table_set(*key_map, "\e[1;2B", to_key("#down+$")); // + + + + + table_set(*key_map, "\e[1;3B", to_key("#down+a")); // + + + + + table_set(*key_map, "\e[1;4B", to_key("#down+A")); // + + + + + table_set(*key_map, "\e[1;5B", to_key("#down+c")); // + + + + + table_set(*key_map, "\e[1;6B", to_key("#down+C")); // + + + + + table_set(*key_map, "\e[1;7B", to_key("#down+w")); // + + + + + table_set(*key_map, "\e[1;8B", to_key("#down+W")); // + + + + + table_set(*key_map, "\e[1;9B", to_key("#down+s")); // + + table_set(*key_map, "\e[1;10B", to_key("#down+S")); // + + table_set(*key_map, "\e[1;11B", to_key("#down+x")); // + + table_set(*key_map, "\e[1;12B", to_key("#down+X")); // + + table_set(*key_map, "\e[1;13B", to_key("#down+y")); // + + table_set(*key_map, "\e[1;14B", to_key("#down+Y")); // + + table_set(*key_map, "\e[1;15B", to_key("#down+z")); // + + table_set(*key_map, "\e[1;16B", to_key("#down+Z")); // + + + // Right // g i k l x + table_set(*key_map, "\e[C", to_key("#right")); // + + + + + + table_set(*key_map, "\e[1;1C", to_key("#right")); // + table_set(*key_map, "\e[1;2C", to_key("#right+$")); // + + + + + table_set(*key_map, "\e[1;3C", to_key("#right+a")); // + + + + + table_set(*key_map, "\e[1;4C", to_key("#right+A")); // + + + + + table_set(*key_map, "\e[1;5C", to_key("#right+c")); // + + + + + table_set(*key_map, "\e[1;6C", to_key("#right+C")); // + + + + + table_set(*key_map, "\e[1;7C", to_key("#right+w")); // + + + + + table_set(*key_map, "\e[1;8C", to_key("#right+W")); // + + + + + table_set(*key_map, "\e[1;9C", to_key("#right+s")); // + + table_set(*key_map, "\e[1;10C", to_key("#right+S")); // + + table_set(*key_map, "\e[1;11C", to_key("#right+x")); // + + table_set(*key_map, "\e[1;12C", to_key("#right+X")); // + + table_set(*key_map, "\e[1;13C", to_key("#right+y")); // + + table_set(*key_map, "\e[1;14C", to_key("#right+Y")); // + + table_set(*key_map, "\e[1;15C", to_key("#right+z")); // + + table_set(*key_map, "\e[1;16C", to_key("#right+Z")); // + + + // Left // g i k l x + table_set(*key_map, "\e[D", to_key("#left")); // + + + + + + table_set(*key_map, "\e[1;1D", to_key("#left")); // + table_set(*key_map, "\e[1;2D", to_key("#left+$")); // + + + + + table_set(*key_map, "\e[1;3D", to_key("#left+a")); // + + + + + table_set(*key_map, "\e[1;4D", to_key("#left+A")); // + + + + + table_set(*key_map, "\e[1;5D", to_key("#left+c")); // + + + + + table_set(*key_map, "\e[1;6D", to_key("#left+C")); // + + + + + table_set(*key_map, "\e[1;7D", to_key("#left+w")); // + + + + + table_set(*key_map, "\e[1;8D", to_key("#left+W")); // + + + + + table_set(*key_map, "\e[1;9D", to_key("#left+s")); // + + table_set(*key_map, "\e[1;10D", to_key("#left+S")); // + + table_set(*key_map, "\e[1;11D", to_key("#left+x")); // + + table_set(*key_map, "\e[1;12D", to_key("#left+X")); // + + table_set(*key_map, "\e[1;13D", to_key("#left+y")); // + + table_set(*key_map, "\e[1;14D", to_key("#left+Y")); // + + table_set(*key_map, "\e[1;15D", to_key("#left+z")); // + + table_set(*key_map, "\e[1;16D", to_key("#left+Z")); // + + + // Home // g i k l x + table_set(*key_map, "\e[1~", to_key("#home")); // + + table_set(*key_map, "\e[H", to_key("#home")); // + + + + + table_set(*key_map, "\e[1;1H", to_key("#home")); // + table_set(*key_map, "\e[1;2H", to_key("#home+$")); // + + + + + table_set(*key_map, "\e[1;3H", to_key("#home+a")); // + + + + + table_set(*key_map, "\e[1;4H", to_key("#home+A")); // + + + + + table_set(*key_map, "\e[1;5H", to_key("#home+c")); // + + + + + table_set(*key_map, "\e[1;6H", to_key("#home+C")); // + + + + + table_set(*key_map, "\e[1;7H", to_key("#home+w")); // + + + + + table_set(*key_map, "\e[1;8H", to_key("#home+W")); // + + + + + table_set(*key_map, "\e[1;9H", to_key("#home+s")); // + + table_set(*key_map, "\e[1;10H", to_key("#home+S")); // + + table_set(*key_map, "\e[1;11H", to_key("#home+x")); // + + table_set(*key_map, "\e[1;12H", to_key("#home+X")); // + + table_set(*key_map, "\e[1;13H", to_key("#home+y")); // + + table_set(*key_map, "\e[1;14H", to_key("#home+Y")); // + + table_set(*key_map, "\e[1;15H", to_key("#home+z")); // + + table_set(*key_map, "\e[1;16H", to_key("#home+Z")); // + + + // End // g i k l x + table_set(*key_map, "\e[4~", to_key("#end")); // + + table_set(*key_map, "\e[F", to_key("#end")); // + + + + + table_set(*key_map, "\e[1;1F", to_key("#end")); // + table_set(*key_map, "\e[1;2F", to_key("#end+$")); // + + + + + table_set(*key_map, "\e[1;3F", to_key("#end+a")); // + + + + + table_set(*key_map, "\e[1;4F", to_key("#end+A")); // + + + + + table_set(*key_map, "\e[1;5F", to_key("#end+c")); // + + + + + table_set(*key_map, "\e[1;6F", to_key("#end+C")); // + + + + + table_set(*key_map, "\e[1;7F", to_key("#end+w")); // + + + + + table_set(*key_map, "\e[1;8F", to_key("#end+W")); // + + + + + table_set(*key_map, "\e[1;9F", to_key("#end+s")); // + + table_set(*key_map, "\e[1;10F", to_key("#end+S")); // + + table_set(*key_map, "\e[1;11F", to_key("#end+x")); // + + table_set(*key_map, "\e[1;12F", to_key("#end+X")); // + + table_set(*key_map, "\e[1;13F", to_key("#end+y")); // + + table_set(*key_map, "\e[1;14F", to_key("#end+Y")); // + + table_set(*key_map, "\e[1;15F", to_key("#end+z")); // + + table_set(*key_map, "\e[1;16F", to_key("#end+Z")); // + + + // Insert // g i k l x + table_set(*key_map, "\e[2~", to_key("#ins")); // + + + + + + table_set(*key_map, "\e[2;1~", to_key("#ins")); // + table_set(*key_map, "\e[2;2~", to_key("#ins+$")); // + + + + + table_set(*key_map, "\e[2;3~", to_key("#ins+a")); // + + + + + table_set(*key_map, "\e[2;4~", to_key("#ins+A")); // + + + + + table_set(*key_map, "\e[2;5~", to_key("#ins+c")); // + + + + + table_set(*key_map, "\e[2;6~", to_key("#ins+C")); // + + + + + table_set(*key_map, "\e[2;7~", to_key("#ins+w")); // + + + + + table_set(*key_map, "\e[2;8~", to_key("#ins+W")); // + + + + + table_set(*key_map, "\e[2;9~", to_key("#ins+s")); // + + table_set(*key_map, "\e[2;10~", to_key("#ins+S")); // + + table_set(*key_map, "\e[2;11~", to_key("#ins+x")); // + + table_set(*key_map, "\e[2;12~", to_key("#ins+X")); // + + table_set(*key_map, "\e[2;13~", to_key("#ins+y")); // + + table_set(*key_map, "\e[2;14~", to_key("#ins+Y")); // + + table_set(*key_map, "\e[2;15~", to_key("#ins+z")); // + + table_set(*key_map, "\e[2;16~", to_key("#ins+Z")); // + + + // Delete // g i k l x + table_set(*key_map, "\e[3~", to_key("#del")); // + + + + + + table_set(*key_map, "\e[3;1~", to_key("#del")); // + table_set(*key_map, "\e[3;2~", to_key("#del+$")); // + + + + + table_set(*key_map, "\e[3;3~", to_key("#del+a")); // + + + + + table_set(*key_map, "\e[3;4~", to_key("#del+A")); // + + + + + table_set(*key_map, "\e[3;5~", to_key("#del+c")); // + + + + + table_set(*key_map, "\e[3;6~", to_key("#del+C")); // + + + + + table_set(*key_map, "\e[3;7~", to_key("#del+w")); // + + + + + table_set(*key_map, "\e[3;8~", to_key("#del+W")); // + + + + + table_set(*key_map, "\e[3;9~", to_key("#del+s")); // + + table_set(*key_map, "\e[3;10~", to_key("#del+S")); // + + table_set(*key_map, "\e[3;11~", to_key("#del+x")); // + + table_set(*key_map, "\e[3;12~", to_key("#del+X")); // + + table_set(*key_map, "\e[3;13~", to_key("#del+y")); // + + table_set(*key_map, "\e[3;14~", to_key("#del+Y")); // + + table_set(*key_map, "\e[3;15~", to_key("#del+z")); // + + table_set(*key_map, "\e[3;16~", to_key("#del+Z")); // + + + // Page Up // g i k l x + table_set(*key_map, "\e[5~", to_key("#pup")); // + + + + + + table_set(*key_map, "\e[5;1~", to_key("#pup")); // + table_set(*key_map, "\e[5;2~", to_key("#pup+$")); // + + + + + table_set(*key_map, "\e[5;3~", to_key("#pup+a")); // + + + + + table_set(*key_map, "\e[5;4~", to_key("#pup+A")); // + + + + + table_set(*key_map, "\e[5;5~", to_key("#pup+c")); // + + + + + table_set(*key_map, "\e[5;6~", to_key("#pup+C")); // + + + + + table_set(*key_map, "\e[5;7~", to_key("#pup+w")); // + + + + + table_set(*key_map, "\e[5;8~", to_key("#pup+W")); // + + + + + table_set(*key_map, "\e[5;9~", to_key("#pup+s")); // + + table_set(*key_map, "\e[5;10~", to_key("#pup+S")); // + + table_set(*key_map, "\e[5;11~", to_key("#pup+x")); // + + table_set(*key_map, "\e[5;12~", to_key("#pup+X")); // + + table_set(*key_map, "\e[5;13~", to_key("#pup+y")); // + + table_set(*key_map, "\e[5;14~", to_key("#pup+Y")); // + + table_set(*key_map, "\e[5;15~", to_key("#pup+z")); // + + table_set(*key_map, "\e[5;16~", to_key("#pup+Z")); // + + + // Page Down // g i k l x + table_set(*key_map, "\e[6~", to_key("#pdown")); // + + + + + + table_set(*key_map, "\e[6;1~", to_key("#pdown")); // + table_set(*key_map, "\e[6;2~", to_key("#pdown+$")); // + + + + + table_set(*key_map, "\e[6;3~", to_key("#pdown+a")); // + + + + + table_set(*key_map, "\e[6;4~", to_key("#pdown+A")); // + + + + + table_set(*key_map, "\e[6;5~", to_key("#pdown+c")); // + + + + + table_set(*key_map, "\e[6;6~", to_key("#pdown+C")); // + + + + + table_set(*key_map, "\e[6;7~", to_key("#pdown+w")); // + + + + + table_set(*key_map, "\e[6;8~", to_key("#pdown+W")); // + + + + + table_set(*key_map, "\e[6;9~", to_key("#pdown+s")); // + + table_set(*key_map, "\e[6;10~", to_key("#pdown+S")); // + + table_set(*key_map, "\e[6;11~", to_key("#pdown+x")); // + + table_set(*key_map, "\e[6;12~", to_key("#pdown+X")); // + + table_set(*key_map, "\e[6;13~", to_key("#pdown+y")); // + + table_set(*key_map, "\e[6;14~", to_key("#pdown+Y")); // + + table_set(*key_map, "\e[6;15~", to_key("#pdown+z")); // + + table_set(*key_map, "\e[6;16~", to_key("#pdown+Z")); // + + + // F1 // g i k l x + table_set(*key_map, "\e[[A", to_key("#f1")); // + + table_set(*key_map, "\e[25~", to_key("#f1+$")); // + + table_set(*key_map, "\eOP", to_key("#f1")); // + + + + + table_set(*key_map, "\eO1P", to_key("#f1+s")); // + + table_set(*key_map, "\eO2P", to_key("#f1+$")); // + + table_set(*key_map, "\eO3P", to_key("#f1+a")); // + + table_set(*key_map, "\eO4P", to_key("#f1+A")); // + + table_set(*key_map, "\eO5P", to_key("#f1+c")); // + + table_set(*key_map, "\eO6P", to_key("#f1+C")); // + + table_set(*key_map, "\eO7P", to_key("#f1+w")); // + + table_set(*key_map, "\eO8P", to_key("#f1+W")); // + + table_set(*key_map, "\e[1P", to_key("#f1")); // + table_set(*key_map, "\e[1;1P", to_key("#f1")); // + table_set(*key_map, "\e[1;2P", to_key("#f1+$")); // + + + + table_set(*key_map, "\e[1;3P", to_key("#f1+a")); // + + + + table_set(*key_map, "\e[1;4P", to_key("#f1+A")); // + + + + table_set(*key_map, "\e[1;5P", to_key("#f1+c")); // + + + + table_set(*key_map, "\e[1;6P", to_key("#f1+C")); // + + + + table_set(*key_map, "\e[1;7P", to_key("#f1+w")); // + + + + table_set(*key_map, "\e[1;8P", to_key("#f1+W")); // + + + + table_set(*key_map, "\e[1;9P", to_key("#f1+s")); // + + table_set(*key_map, "\e[1;10P", to_key("#f1+S")); // + + table_set(*key_map, "\e[1;11P", to_key("#f1+x")); // + + table_set(*key_map, "\e[1;12P", to_key("#f1+X")); // + + table_set(*key_map, "\e[1;13P", to_key("#f1+y")); // + + table_set(*key_map, "\e[1;14P", to_key("#f1+Y")); // + + table_set(*key_map, "\e[1;15P", to_key("#f1+z")); // + + table_set(*key_map, "\e[1;16P", to_key("#f1+Z")); // + + + // F2 // g i k l x + table_set(*key_map, "\e[[B", to_key("#f2")); // + + table_set(*key_map, "\e[26~", to_key("#f2+$")); // + + table_set(*key_map, "\eOQ", to_key("#f2")); // + + + + + table_set(*key_map, "\eO1Q", to_key("#f2+s")); // + + table_set(*key_map, "\eO2Q", to_key("#f2+$")); // + + table_set(*key_map, "\eO3Q", to_key("#f2+a")); // + + table_set(*key_map, "\eO4Q", to_key("#f2+A")); // + + table_set(*key_map, "\eO5Q", to_key("#f2+c")); // + + table_set(*key_map, "\eO6Q", to_key("#f2+C")); // + + table_set(*key_map, "\eO7Q", to_key("#f2+w")); // + + table_set(*key_map, "\eO8Q", to_key("#f2+W")); // + + table_set(*key_map, "\e[1Q", to_key("#f2")); // + table_set(*key_map, "\e[1;1Q", to_key("#f2")); // + table_set(*key_map, "\e[1;2Q", to_key("#f2+$")); // + + + + table_set(*key_map, "\e[1;3Q", to_key("#f2+a")); // + + + + table_set(*key_map, "\e[1;4Q", to_key("#f2+A")); // + + + + table_set(*key_map, "\e[1;5Q", to_key("#f2+c")); // + + + + table_set(*key_map, "\e[1;6Q", to_key("#f2+C")); // + + + + table_set(*key_map, "\e[1;7Q", to_key("#f2+w")); // + + + + table_set(*key_map, "\e[1;8Q", to_key("#f2+W")); // + + + + table_set(*key_map, "\e[1;9Q", to_key("#f2+s")); // + + table_set(*key_map, "\e[1;10Q", to_key("#f2+S")); // + + table_set(*key_map, "\e[1;11Q", to_key("#f2+x")); // + + table_set(*key_map, "\e[1;12Q", to_key("#f2+X")); // + + table_set(*key_map, "\e[1;13Q", to_key("#f2+y")); // + + table_set(*key_map, "\e[1;14Q", to_key("#f2+Y")); // + + table_set(*key_map, "\e[1;15Q", to_key("#f2+z")); // + + table_set(*key_map, "\e[1;16Q", to_key("#f2+Z")); // + + + // F3 // g i k l x + table_set(*key_map, "\e[[C", to_key("#f3")); // + + table_set(*key_map, "\e[28~", to_key("#f3+$")); // + + table_set(*key_map, "\eOR", to_key("#f3")); // + + + + + table_set(*key_map, "\eO1R", to_key("#f3+s")); // + + table_set(*key_map, "\eO2R", to_key("#f3+$")); // + + table_set(*key_map, "\eO3R", to_key("#f3+a")); // + + table_set(*key_map, "\eO4R", to_key("#f3+A")); // + + table_set(*key_map, "\eO5R", to_key("#f3+c")); // + + table_set(*key_map, "\eO6R", to_key("#f3+C")); // + + table_set(*key_map, "\eO7R", to_key("#f3+w")); // + + table_set(*key_map, "\eO8R", to_key("#f3+W")); // + + table_set(*key_map, "\e[1R", to_key("#f3")); // + table_set(*key_map, "\e[1;1R", to_key("#f3")); // + table_set(*key_map, "\e[1;2R", to_key("#f3+$")); // + + + + table_set(*key_map, "\e[1;3R", to_key("#f3+a")); // + + + + table_set(*key_map, "\e[1;4R", to_key("#f3+A")); // + + + + table_set(*key_map, "\e[1;5R", to_key("#f3+c")); // + + + + table_set(*key_map, "\e[1;6R", to_key("#f3+C")); // + + + + table_set(*key_map, "\e[1;7R", to_key("#f3+w")); // + + + + table_set(*key_map, "\e[1;8R", to_key("#f3+W")); // + + + + table_set(*key_map, "\e[1;9R", to_key("#f3+s")); // + + table_set(*key_map, "\e[1;10R", to_key("#f3+S")); // + + table_set(*key_map, "\e[1;11R", to_key("#f3+x")); // + + table_set(*key_map, "\e[1;12R", to_key("#f3+X")); // + + table_set(*key_map, "\e[1;13R", to_key("#f3+y")); // + + table_set(*key_map, "\e[1;14R", to_key("#f3+Y")); // + + table_set(*key_map, "\e[1;15R", to_key("#f3+z")); // + + table_set(*key_map, "\e[1;16R", to_key("#f3+Z")); // + + + // F4 // g i k l x + table_set(*key_map, "\e[[D", to_key("#f4")); // + + table_set(*key_map, "\e[29~", to_key("#f4+$")); // + + table_set(*key_map, "\eOS", to_key("#f4")); // + + + + + table_set(*key_map, "\eO1S", to_key("#f4+s")); // + + table_set(*key_map, "\eO2S", to_key("#f4+$")); // + + table_set(*key_map, "\eO3S", to_key("#f4+a")); // + + table_set(*key_map, "\eO4S", to_key("#f4+A")); // + + table_set(*key_map, "\eO5S", to_key("#f4+c")); // + + table_set(*key_map, "\eO6S", to_key("#f4+C")); // + + table_set(*key_map, "\eO7S", to_key("#f4+w")); // + + table_set(*key_map, "\eO8S", to_key("#f4+W")); // + + table_set(*key_map, "\e[1S", to_key("#f4")); // + table_set(*key_map, "\e[1;1S", to_key("#f4")); // + table_set(*key_map, "\e[1;2S", to_key("#f4+$")); // + + + + table_set(*key_map, "\e[1;3S", to_key("#f4+a")); // + + + + table_set(*key_map, "\e[1;4S", to_key("#f4+A")); // + + + + table_set(*key_map, "\e[1;5S", to_key("#f4+c")); // + + + + table_set(*key_map, "\e[1;6S", to_key("#f4+C")); // + + + + table_set(*key_map, "\e[1;7S", to_key("#f4+w")); // + + + + table_set(*key_map, "\e[1;8S", to_key("#f4+W")); // + + + + table_set(*key_map, "\e[1;9S", to_key("#f4+s")); // + + table_set(*key_map, "\e[1;10S", to_key("#f4+S")); // + + table_set(*key_map, "\e[1;11S", to_key("#f4+x")); // + + table_set(*key_map, "\e[1;12S", to_key("#f4+X")); // + + table_set(*key_map, "\e[1;13S", to_key("#f4+y")); // + + table_set(*key_map, "\e[1;14S", to_key("#f4+Y")); // + + table_set(*key_map, "\e[1;15S", to_key("#f4+z")); // + + table_set(*key_map, "\e[1;16S", to_key("#f4+Z")); // + + + // F5 // g i k l x + table_set(*key_map, "\e[[E", to_key("#f5")); // + + table_set(*key_map, "\e[31~", to_key("#f5+$")); // + + table_set(*key_map, "\e[15~", to_key("#f5")); // + + + + + table_set(*key_map, "\e[15;1~", to_key("#f5")); // + table_set(*key_map, "\e[15;2~", to_key("#f5+$")); // + + + + + table_set(*key_map, "\e[15;3~", to_key("#f5+a")); // + + + + + table_set(*key_map, "\e[15;4~", to_key("#f5+A")); // + + + + + table_set(*key_map, "\e[15;5~", to_key("#f5+c")); // + + + + + table_set(*key_map, "\e[15;6~", to_key("#f5+C")); // + + + + + table_set(*key_map, "\e[15;7~", to_key("#f5+w")); // + + + + + table_set(*key_map, "\e[15;8~", to_key("#f5+W")); // + + + + + table_set(*key_map, "\e[15;9~", to_key("#f5+s")); // + + table_set(*key_map, "\e[15;10~",to_key("#f5+S")); // + + table_set(*key_map, "\e[15;11~",to_key("#f5+x")); // + + table_set(*key_map, "\e[15;12~",to_key("#f5+X")); // + + table_set(*key_map, "\e[15;13~",to_key("#f5+y")); // + + table_set(*key_map, "\e[15;14~",to_key("#f5+Y")); // + + table_set(*key_map, "\e[15;15~",to_key("#f5+z")); // + + table_set(*key_map, "\e[15;16~",to_key("#f5+Z")); // + + + // F6 // g i k l x + table_set(*key_map, "\e[32~", to_key("#f6+$")); // + + table_set(*key_map, "\e[17~", to_key("#f6")); // + + + + + + table_set(*key_map, "\e[17;1~", to_key("#f6")); // + table_set(*key_map, "\e[17;2~", to_key("#f6+$")); // + + + + + table_set(*key_map, "\e[17;3~", to_key("#f6+a")); // + + + + + table_set(*key_map, "\e[17;4~", to_key("#f6+A")); // + + + + + table_set(*key_map, "\e[17;5~", to_key("#f6+c")); // + + + + + table_set(*key_map, "\e[17;6~", to_key("#f6+C")); // + + + + + table_set(*key_map, "\e[17;7~", to_key("#f6+w")); // + + + + + table_set(*key_map, "\e[17;8~", to_key("#f6+W")); // + + + + + table_set(*key_map, "\e[17;9~", to_key("#f6+s")); // + + table_set(*key_map, "\e[17;10~",to_key("#f6+S")); // + + table_set(*key_map, "\e[17;11~",to_key("#f6+x")); // + + table_set(*key_map, "\e[17;12~",to_key("#f6+X")); // + + table_set(*key_map, "\e[17;13~",to_key("#f6+y")); // + + table_set(*key_map, "\e[17;14~",to_key("#f6+Y")); // + + table_set(*key_map, "\e[17;15~",to_key("#f6+z")); // + + table_set(*key_map, "\e[17;16~",to_key("#f6+Z")); // + + + // F7 // g i k l x + table_set(*key_map, "\e[33~", to_key("#f7+$")); // + + table_set(*key_map, "\e[18~", to_key("#f7")); // + + + + + + table_set(*key_map, "\e[18;1~", to_key("#f7")); // + table_set(*key_map, "\e[18;2~", to_key("#f7+$")); // + + + + + table_set(*key_map, "\e[18;3~", to_key("#f7+a")); // + + + + + table_set(*key_map, "\e[18;4~", to_key("#f7+A")); // + + + + + table_set(*key_map, "\e[18;5~", to_key("#f7+c")); // + + + + + table_set(*key_map, "\e[18;6~", to_key("#f7+C")); // + + + + + table_set(*key_map, "\e[18;7~", to_key("#f7+w")); // + + + + + table_set(*key_map, "\e[18;8~", to_key("#f7+W")); // + + + + + table_set(*key_map, "\e[18;9~", to_key("#f7+s")); // + + table_set(*key_map, "\e[18;10~",to_key("#f7+S")); // + + table_set(*key_map, "\e[18;11~",to_key("#f7+x")); // + + table_set(*key_map, "\e[18;12~",to_key("#f7+X")); // + + table_set(*key_map, "\e[18;13~",to_key("#f7+y")); // + + table_set(*key_map, "\e[18;14~",to_key("#f7+Y")); // + + table_set(*key_map, "\e[18;15~",to_key("#f7+z")); // + + table_set(*key_map, "\e[18;16~",to_key("#f7+Z")); // + + + // F8 // g i k l x + table_set(*key_map, "\e[34~", to_key("#f8+$")); // + + table_set(*key_map, "\e[19~", to_key("#f8")); // + + + + + + table_set(*key_map, "\e[19;1~", to_key("#f8")); // + table_set(*key_map, "\e[19;2~", to_key("#f8+$")); // + + + + + table_set(*key_map, "\e[19;3~", to_key("#f8+a")); // + + + + + table_set(*key_map, "\e[19;4~", to_key("#f8+A")); // + + + + + table_set(*key_map, "\e[19;5~", to_key("#f8+c")); // + + + + + table_set(*key_map, "\e[19;6~", to_key("#f8+C")); // + + + + + table_set(*key_map, "\e[19;7~", to_key("#f8+w")); // + + + + + table_set(*key_map, "\e[19;8~", to_key("#f8+W")); // + + + + + table_set(*key_map, "\e[19;9~", to_key("#f8+s")); // + + table_set(*key_map, "\e[19;10~",to_key("#f8+S")); // + + table_set(*key_map, "\e[19;11~",to_key("#f8+x")); // + + table_set(*key_map, "\e[19;12~",to_key("#f8+X")); // + + table_set(*key_map, "\e[19;13~",to_key("#f8+y")); // + + table_set(*key_map, "\e[19;14~",to_key("#f8+Y")); // + + table_set(*key_map, "\e[19;15~",to_key("#f8+z")); // + + table_set(*key_map, "\e[19;16~",to_key("#f8+Z")); // + + + // F9 // g i k l x + table_set(*key_map, "\e[20~", to_key("#f9")); // + + + + + + table_set(*key_map, "\e[20;1~", to_key("#f9")); // + table_set(*key_map, "\e[20;2~", to_key("#f9+$")); // + + + + + table_set(*key_map, "\e[20;3~", to_key("#f9+a")); // + + + + + table_set(*key_map, "\e[20;4~", to_key("#f9+A")); // + + + + + table_set(*key_map, "\e[20;5~", to_key("#f9+c")); // + + + + + table_set(*key_map, "\e[20;6~", to_key("#f9+C")); // + + + + + table_set(*key_map, "\e[20;7~", to_key("#f9+w")); // + + + + + table_set(*key_map, "\e[20;8~", to_key("#f9+W")); // + + + + + table_set(*key_map, "\e[20;9~", to_key("#f9+s")); // + + table_set(*key_map, "\e[20;10~",to_key("#f9+S")); // + + table_set(*key_map, "\e[20;11~",to_key("#f9+x")); // + + table_set(*key_map, "\e[20;12~",to_key("#f9+X")); // + + table_set(*key_map, "\e[20;13~",to_key("#f9+y")); // + + table_set(*key_map, "\e[20;14~",to_key("#f9+Y")); // + + table_set(*key_map, "\e[20;15~",to_key("#f9+z")); // + + table_set(*key_map, "\e[20;16~",to_key("#f9+Z")); // + + + // F10 // g i k l x + table_set(*key_map, "\e[21~", to_key("#f10")); // + + + + + + table_set(*key_map, "\e[21;1~", to_key("#f10")); // + table_set(*key_map, "\e[21;2~", to_key("#f10+$")); // + + + + + table_set(*key_map, "\e[21;3~", to_key("#f10+a")); // + + + + + table_set(*key_map, "\e[21;4~", to_key("#f10+A")); // + + + + + table_set(*key_map, "\e[21;5~", to_key("#f10+c")); // + + + + + table_set(*key_map, "\e[21;6~", to_key("#f10+C")); // + + + + + table_set(*key_map, "\e[21;7~", to_key("#f10+w")); // + + + + + table_set(*key_map, "\e[21;8~", to_key("#f10+W")); // + + + + + table_set(*key_map, "\e[21;9~", to_key("#f10+s")); // + + table_set(*key_map, "\e[21;10~",to_key("#f10+S")); // + + table_set(*key_map, "\e[21;11~",to_key("#f10+x")); // + + table_set(*key_map, "\e[21;12~",to_key("#f10+X")); // + + table_set(*key_map, "\e[21;13~",to_key("#f10+y")); // + + table_set(*key_map, "\e[21;14~",to_key("#f10+Y")); // + + table_set(*key_map, "\e[21;15~",to_key("#f10+z")); // + + table_set(*key_map, "\e[21;16~",to_key("#f10+Z")); // + + + // F11 // g i k l x + table_set(*key_map, "\e[23~", to_key("#f11")); // + + + + + + table_set(*key_map, "\e[23;1~", to_key("#f11")); // + table_set(*key_map, "\e[23;2~", to_key("#f11+$")); // + + + + + table_set(*key_map, "\e[23;3~", to_key("#f11+a")); // + + + + + table_set(*key_map, "\e[23;4~", to_key("#f11+A")); // + + + + + table_set(*key_map, "\e[23;5~", to_key("#f11+c")); // + + + + + table_set(*key_map, "\e[23;6~", to_key("#f11+C")); // + + + + + table_set(*key_map, "\e[23;7~", to_key("#f11+w")); // + + + + + table_set(*key_map, "\e[23;8~", to_key("#f11+W")); // + + + + + table_set(*key_map, "\e[23;9~", to_key("#f11+s")); // + + table_set(*key_map, "\e[23;10~",to_key("#f11+S")); // + + table_set(*key_map, "\e[23;11~",to_key("#f11+x")); // + + table_set(*key_map, "\e[23;12~",to_key("#f11+X")); // + + table_set(*key_map, "\e[23;13~",to_key("#f11+y")); // + + table_set(*key_map, "\e[23;14~",to_key("#f11+Y")); // + + table_set(*key_map, "\e[23;15~",to_key("#f11+z")); // + + table_set(*key_map, "\e[23;16~",to_key("#f11+Z")); // + + + // F12 // g i k l x + table_set(*key_map, "\e[24~", to_key("#f12")); // + + + + + + table_set(*key_map, "\e[24;1~", to_key("#f12")); // + table_set(*key_map, "\e[24;2~", to_key("#f12+$")); // + + + + + table_set(*key_map, "\e[24;3~", to_key("#f12+a")); // + + + + + table_set(*key_map, "\e[24;4~", to_key("#f12+A")); // + + + + + table_set(*key_map, "\e[24;5~", to_key("#f12+c")); // + + + + + table_set(*key_map, "\e[24;6~", to_key("#f12+C")); // + + + + + table_set(*key_map, "\e[24;7~", to_key("#f12+w")); // + + + + + table_set(*key_map, "\e[24;8~", to_key("#f12+W")); // + + + + + table_set(*key_map, "\e[24;9~", to_key("#f12+s")); // + + table_set(*key_map, "\e[24;10~",to_key("#f12+S")); // + + table_set(*key_map, "\e[24;11~",to_key("#f12+x")); // + + table_set(*key_map, "\e[24;12~",to_key("#f12+X")); // + + table_set(*key_map, "\e[24;13~",to_key("#f12+y")); // + + table_set(*key_map, "\e[24;14~",to_key("#f12+Y")); // + + table_set(*key_map, "\e[24;15~",to_key("#f12+z")); // + + table_set(*key_map, "\e[24;16~",to_key("#f12+Z")); // + +} -- cgit v1.2.3 From b47287aaa3cfa384ec683ff58e0d247e8bad32b1 Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 21 Mar 2024 00:50:42 +0000 Subject: Fix get_key to support escape codes. --- modules/TUI/key_map.jai | 2 +- modules/TUI/module.jai | 48 +++++++++++++++++------------------------------- ttt.jai | 13 ++++++++++--- 3 files changed, 28 insertions(+), 35 deletions(-) (limited to 'modules/TUI/key_map.jai') diff --git a/modules/TUI/key_map.jai b/modules/TUI/key_map.jai index 42acabf..b272253 100644 --- a/modules/TUI/key_map.jai +++ b/modules/TUI/key_map.jai @@ -31,7 +31,7 @@ setup_key_map :: () { */ // Up // g i k l x - // table_set(*key_map, "\e[A", to_key("#up")); // + + + + + + table_set(*key_map, "\e[A", to_key("#up")); // + + + + + table_set(*key_map, "\e[1;1A", to_key("#up")); // table_set(*key_map, "\e[1;2A", to_key("#up+$")); // + + + + table_set(*key_map, "\e[1;3A", to_key("#up+a")); // + + + + diff --git a/modules/TUI/module.jai b/modules/TUI/module.jai index d93e4ff..93e410e 100644 --- a/modules/TUI/module.jai +++ b/modules/TUI/module.jai @@ -126,6 +126,8 @@ Colors8b :: struct { White :: 15; } +// Fix color tables using this: https://devmemo.io/cheatsheets/terminal_escape_code/ + // TODO Maybe rename. set_style_colors :: (foreground: u8, background: u8) { print( @@ -261,15 +263,6 @@ set_next_key :: (key: Key) { get_key :: (timeout_milliseconds: s32 = -1) -> Key { assert_is_initialized(); - /* - TODO - get_key already deals with utf8 codes, but we don't know when we're receiving ANSI escape codes. If initial key is escape and other keys are awaiting in the input buffer, we need to parse them as escaped sequences. See wikiedia* for help on that. Lets use the escape sequences used on windows amd forget all others. Those should be the most used ones; at least they are the cross-platform compatible ones :P - * https://en.m.wikipedia.org/wiki/ANSI_escape_code - - Check this - https://devmemo.io/cheatsheets/terminal_escape_code/ - */ - // BBBB BBBB & 1100 0000 == 10XX XXXX -> is continuation byte is_utf8_continuation_byte :: inline (byte: u8) -> bool { @@ -321,38 +314,31 @@ get_key :: (timeout_milliseconds: s32 = -1) -> Key { if input_string.count == 0 return Keys.None; - // Assume we're parsing just a single char. + // By default, parse a single UTF8 character (1 to 4 bytes). to_parse := input_string; - to_parse.count = 1; - - // Try to parse UTF8 character. - if is_utf8_continuation_byte(input_string[0]) { - to_parse.count = count_utf8_bytes(input_string[0]); - } - + to_parse.count = count_utf8_bytes(input_string[0]); + defer advance(*input_string, to_parse.count); // Advance over parsed input. + // Try to parse escape code. if input_string[0] == #char "\e" && input_string.count > 1 { - assert(input_string.count <= KEY_SIZE, "Received oversized terminal sequence."); // TODO - to_parse.count = ifx input_string.count > KEY_SIZE then KEY_SIZE else input_string.count; // TODO We should look into the input_string and search for the following escape sequence or somehting!? - // WIP HERE - // A possible way to solve this is to create a LUT, and then, grow the to_parse.count from 2 to KEY_SIZE and return as soon - // as we ding a match on the LUT. - // If the LUT is too big... maybe use a hash-table. + // Limit number of chars to parse. + to_parse.count = ifx input_string.count > KEY_SIZE then KEY_SIZE else input_string.count; - // TEMPORARY HACK + // Search for the longest escape code. key, success := table_find(*key_map, to_parse); + while success == false && to_parse.count > 1 { + to_parse.count -= 1; + key, success = table_find(*key_map, to_parse); + } + + // If an escape code was found, use it. if success { - advance(*input_string, to_parse.count); return key; } - TODO If failed to parse... lets return a single char... but it's not working! - else { - to_parse.count = 1; - } + // else { ... } If we entered this block and did not succeed, then we'll return a single escape character.รข } - - advance(*input_string, to_parse.count); + return to_key(to_parse); } diff --git a/ttt.jai b/ttt.jai index 2921ff0..9b08f6d 100644 --- a/ttt.jai +++ b/ttt.jai @@ -1332,7 +1332,12 @@ main :: () { TUI.set_terminal_title("bazinga"); key: TUI.Key = #char "d"; last_none_char := "X"; + + size_r, size_c := TUI.get_terminal_size(); + TUI.clear_terminal(); + TUI.draw_box(1, 1, size_c, size_r); drop_down := 0; + while(key != #char "q") { __mark := get_temporary_storage_mark(); @@ -1345,7 +1350,9 @@ main :: () { case TUI.Keys.Resize; #through; case #char "c"; { + size_r, size_c = TUI.get_terminal_size(); TUI.clear_terminal(); + TUI.draw_box(1, 1, size_c, size_r); drop_down = 0; } @@ -1369,13 +1376,13 @@ main :: () { drop_down += 1; } } - size_r, size_c := TUI.get_terminal_size(); - TUI.draw_box(1, 1, size_c, size_r); + + x := ifx size_r > 1 then size_r-1 else 1; y := ifx size_c > 24 then size_c-24 else 1; + TUI.set_cursor_position(x, y); print("size(CxR): %x%\n", size_c, size_r); - key = TUI.get_key(1000); set_temporary_storage_mark(__mark); -- cgit v1.2.3 From 1f2afe4db186342bda551e96bcd1d9b029d7c5ba Mon Sep 17 00:00:00 2001 From: dam Date: Fri, 19 Apr 2024 12:36:18 +0100 Subject: Avoid multiple initializations of key_map. --- modules/TUI/key_map.jai | 3 +++ 1 file changed, 3 insertions(+) (limited to 'modules/TUI/key_map.jai') diff --git a/modules/TUI/key_map.jai b/modules/TUI/key_map.jai index b272253..7a074b2 100644 --- a/modules/TUI/key_map.jai +++ b/modules/TUI/key_map.jai @@ -3,6 +3,9 @@ key_map: Table(string, Key); setup_key_map :: () { + + if key_map.count > 0 then return; + /* This table was created/tested using the following terminals: - g: gnome (terminal) -- cgit v1.2.3 From bdea73c8349c2c918befad4120f49f9826d270dc Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 16 May 2024 02:42:04 +0100 Subject: Imported new module structure. --- Test_IntSatArith.jai | 304 ---------------------- modules/Integer_Saturating_Arithmetic.jai | 416 ------------------------------ modules/Saturation/module.jai | 416 ++++++++++++++++++++++++++++++ modules/Saturation/tests.jai | 304 ++++++++++++++++++++++ modules/TUI/key_map.jai | 401 ++++++++++++++-------------- modules/TUI/tests.jai | 19 +- modules/UTF8.jai | 128 --------- modules/UTF8/module.jai | 128 +++++++++ modules/UTF8/tests.jai | 5 + sizeof.c | 50 ---- ttt.jai | 2 +- 11 files changed, 1057 insertions(+), 1116 deletions(-) delete mode 100644 Test_IntSatArith.jai delete mode 100644 modules/Integer_Saturating_Arithmetic.jai create mode 100644 modules/Saturation/module.jai create mode 100644 modules/Saturation/tests.jai delete mode 100644 modules/UTF8.jai create mode 100644 modules/UTF8/module.jai create mode 100644 modules/UTF8/tests.jai delete mode 100644 sizeof.c (limited to 'modules/TUI/key_map.jai') diff --git a/Test_IntSatArith.jai b/Test_IntSatArith.jai deleted file mode 100644 index 2128f7b..0000000 --- a/Test_IntSatArith.jai +++ /dev/null @@ -1,304 +0,0 @@ -// Tests for integer saturating arighmetic procedures. - -#import "Basic"; -#import "Compiler"; -#import "Math"; -#import "String"; -#import "Integer_Saturating_Arithmetic"; - -main :: () { - - write_strings( - "#=======================#\n", - "# Basic tests #\n" - ); - - test_op :: (operation: string, x: $Tx, y: $Ty, result: $Tr, type: Type, saturated: bool, remainder: Tr = 0) -> errors_found: int #expand { - - print_test_call :: (operation: string) -> string { - str: string = ---; - if operation != "div" { - TEST_CALL :: #string DONE - t_result, t_saturated := OP(cast(Tx)x, cast(Ty)y); - if result != t_result print("%_%(%, %) = %0%0\n", operation, type, x, y, result, ifx saturated then " : saturated"); - DONE - str = replace(TEST_CALL, "OP", operation); - } else { - TEST_CALL :: #string DONE - t_result, t_remainder, t_saturated := OP(cast(Tx)x, cast(Ty)y); - if result != t_result print("%_%(%, %) = % + %0%0\n", operation, type, x, y, result, remainder, ifx saturated then " : saturated"); - DONE - str = replace(TEST_CALL, "OP", operation); - } - return str; - } - - #insert #run print_test_call(operation); - - errors := 0; - if result != t_result { errors += 1; print(" > incorrect result value: got % expected %\n", t_result, result); }; - if type != type_of(t_result) { errors += 1; print(" > incorrect result type: got % expected %\n", type_of(t_result), type); }; - if saturated != t_saturated { errors += 1; print(" > incorrect saturated flag: got % expected %\n", t_saturated, saturated); }; - #if operation == "div" { - if remainder != t_remainder { errors += 1; print(" > incorrect remainder value: got % expected %\n", t_remainder, remainder); }; - } - return errors; - } - - errors := 0; - - // Test signed add. - errors += test_op("add", cast( s8) S8_MAX, cast( s8)1, S8_MAX, s8, true); - errors += test_op("add", cast(s16)S16_MAX, cast( u8)1, S16_MAX, s16, true); - errors += test_op("add", cast(s32)S32_MAX, cast(s32)1, S32_MAX, s32, true); - errors += test_op("add", cast(s64)S64_MAX, cast(u32)1, S64_MAX, s64, true); - - errors += test_op("add", cast( s8) S8_MAX, cast( s8) S8_MIN, -1, s8, false); - errors += test_op("add", cast(s16)S16_MAX, cast(s16)S16_MIN, -1, s16, false); - errors += test_op("add", cast(s32)S32_MAX, cast(s32)S32_MIN, -1, s32, false); - errors += test_op("add", cast(s64)S64_MAX, cast(s64)S64_MIN, -1, s64, false); - - // Test unsigned add. - errors += test_op("add", cast( u8) U8_MAX, cast( u8)1, U8_MAX, u8, true); - errors += test_op("add", cast(u16)U16_MAX, cast(u16)1, U16_MAX, u16, true); - errors += test_op("add", cast(u32)U32_MAX, cast(u32)1, U32_MAX, u32, true); - errors += test_op("add", cast(u64)U64_MAX, cast(u64)1, U64_MAX, u64, true); - - errors += test_op("add", cast( u8) U8_MAX, cast( u8)0, U8_MAX, u8, false); - errors += test_op("add", cast(u16)U16_MAX, cast(u16)0, U16_MAX, u16, false); - errors += test_op("add", cast(u32)U32_MAX, cast(u32)0, U32_MAX, u32, false); - errors += test_op("add", cast(u64)U64_MAX, cast(u64)0, U64_MAX, u64, false); - - // Test signed sub. - errors += test_op("sub", cast( s8) S8_MIN, cast( s8)1, S8_MIN, s8, true); - errors += test_op("sub", cast(s16)S16_MIN, cast( u8)1, S16_MIN, s16, true); - errors += test_op("sub", cast(s32)S32_MIN, cast(s32)1, S32_MIN, s32, true); - errors += test_op("sub", cast(s64)S64_MIN, cast(u32)1, S64_MIN, s64, true); - - errors += test_op("sub", cast( s8)-1, cast( s8) S8_MAX, S8_MIN, s8, false); - errors += test_op("sub", cast(s16)-1, cast(s16)S16_MAX, S16_MIN, s16, false); - errors += test_op("sub", cast(s32)-1, cast(s32)S32_MAX, S32_MIN, s32, false); - errors += test_op("sub", cast(s64)-1, cast(s64)S64_MAX, S64_MIN, s64, false); - - // Test unsigned sub. - errors += test_op("sub", cast( u8)1, cast( u8) U8_MAX, 0, u8, true); - errors += test_op("sub", cast( u8)1, cast(u16)U16_MAX, 0, u16, true); - errors += test_op("sub", cast(u32)1, cast(u32)U32_MAX, 0, u32, true); - errors += test_op("sub", cast(u32)1, cast(u64)U64_MAX, 0, u64, true); - - errors += test_op("sub", cast( u8) U8_MAX, cast( u8)0, U8_MAX, u8, false); - errors += test_op("sub", cast(u16)U16_MAX, cast( u8)0, U16_MAX, u16, false); - errors += test_op("sub", cast(u32)U32_MAX, cast(u32)0, U32_MAX, u32, false); - errors += test_op("sub", cast(u64)U64_MAX, cast(u32)0, U64_MAX, u64, false); - - // Test signed mul. - errors += test_op("mul", cast( s8) S8_MIN, cast( s8)-1, S8_MAX, s8, true); - errors += test_op("mul", cast(s16)S16_MIN, cast( s8)-1, S16_MAX, s16, true); - errors += test_op("mul", cast(s32)S32_MIN, cast(s32)-1, S32_MAX, s32, true); - errors += test_op("mul", cast(s64)S64_MIN, cast(s32)-1, S64_MAX, s64, true); - - errors += test_op("mul", cast( s8) S8_MAX, cast( s8)-2, S8_MIN, s8, true); - errors += test_op("mul", cast(s16)S16_MAX, cast( s8)-2, S16_MIN, s16, true); - errors += test_op("mul", cast(s32)S32_MAX, cast(s32)-2, S32_MIN, s32, true); - errors += test_op("mul", cast(s64)S64_MAX, cast(s32)-2, S64_MIN, s64, true); - - errors += test_op("mul", cast( s8)-2, cast( s8) S8_MAX, S8_MIN, s8, true); - errors += test_op("mul", cast( s8)-2, cast(s16)S16_MAX, S16_MIN, s16, true); - errors += test_op("mul", cast(s32)-2, cast(s32)S32_MAX, S32_MIN, s32, true); - errors += test_op("mul", cast(s32)-2, cast(s64)S64_MAX, S64_MIN, s64, true); - - errors += test_op("mul", cast( s8) S8_MAX, cast( s8)2, S8_MAX, s8, true); - errors += test_op("mul", cast(s16)S16_MAX, cast( s8)2, S16_MAX, s16, true); - errors += test_op("mul", cast(s32)S32_MAX, cast(s32)2, S32_MAX, s32, true); - errors += test_op("mul", cast(s64)S64_MAX, cast(s32)2, S64_MAX, s64, true); - - errors += test_op("mul", cast( s8) S8_MAX, cast( s8)-1, -S8_MAX, s8, false); - errors += test_op("mul", cast(s16)S16_MAX, cast( s8)-1, -S16_MAX, s16, false); - errors += test_op("mul", cast(s32)S32_MAX, cast(s32)-1, -S32_MAX, s32, false); - errors += test_op("mul", cast(s64)S64_MAX, cast(s32)-1, -S64_MAX, s64, false); - - errors += test_op("mul", cast( s8) S8_MAX, cast( s8)0, 0, s8, false); - errors += test_op("mul", cast(s16)S16_MAX, cast( u8)0, 0, s16, false); - errors += test_op("mul", cast(s32)S32_MAX, cast(s32)0, 0, s32, false); - errors += test_op("mul", cast(s64)S64_MAX, cast(u32)0, 0, s64, false); - - // Test unsigned mul. - errors += test_op("mul", cast( u8) U8_MAX, cast( u8)1, U8_MAX, u8, false); - errors += test_op("mul", cast(u16)U16_MAX, cast( u8)1, U16_MAX, u16, false); - errors += test_op("mul", cast(u32)U32_MAX, cast(u32)1, U32_MAX, u32, false); - errors += test_op("mul", cast(u64)U64_MAX, cast(u32)1, U64_MAX, u64, false); - - errors += test_op("mul", cast( u8) U8_MAX, cast( u8)2, U8_MAX, u8, true); - errors += test_op("mul", cast(u16)U16_MAX, cast( u8)2, U16_MAX, u16, true); - errors += test_op("mul", cast(u32)U32_MAX, cast(u32)2, U32_MAX, u32, true); - errors += test_op("mul", cast(u64)U64_MAX, cast(u32)2, U64_MAX, u64, true); - - // Test signed div. - errors += test_op("div", cast( s8) S8_MIN, cast( s8)-1, S8_MAX, s8, true, -1); - errors += test_op("div", cast(s16)S16_MIN, cast( s8)-1, S16_MAX, s16, true, -1); - errors += test_op("div", cast(s32)S32_MIN, cast(s32)-1, S32_MAX, s32, true, -1); - errors += test_op("div", cast(s64)S64_MIN, cast(s32)-1, S64_MAX, s64, true, -1); - - errors += test_op("div", cast( s8) S8_MAX, cast( s8)-2, - S8_MAX/2, s8, false, 1); - errors += test_op("div", cast(s16)S16_MAX, cast( s8)-2, -S16_MAX/2, s16, false, 1); - errors += test_op("div", cast(s32)S32_MAX, cast(s32)-2, -S32_MAX/2, s32, false, 1); - errors += test_op("div", cast(s64)S64_MAX, cast(s32)-2, -S64_MAX/2, s64, false, 1); - - errors += test_op("div", cast( s8)15, cast( s8)5, 3, s8, false, 0); - errors += test_op("div", cast( u8)15, cast(s16)7, 2, s16, false, 1); - errors += test_op("div", cast(s16)15, cast(s32)13, 1, s32, false, 2); - errors += test_op("div", cast(u16)100, cast(s64)3, 33, s64, false, 1); - - // Test unsigned div. - errors += test_op("div", cast( u8) U8_MAX, cast( u8)2, U8_MAX/2, u8, false, 1); - errors += test_op("div", cast(u16)U16_MAX, cast( u8)2, U16_MAX/2, u16, false, 1); - errors += test_op("div", cast(u32)U32_MAX, cast(u32)2, U32_MAX/2, u32, false, 1); - errors += test_op("div", cast(u64)U64_MAX, cast(u32)2, U64_MAX/2, u64, false, 1); - - if errors > 0 print("# Found % %!\n", errors, ifx errors == 1 then "error" else "errors"); else print(" No errors found.\n"); - - write_strings( - "#=======================#\n", - "# Benchmarks #\n" - ); - - #import "Random"; - - performance_test :: ($operation: string, $type: Type, print_result: bool = true) -> ops_per_us_gen: float, ops_per_us_asm: float { - - #if type == u8 { MIN :: 0; MAX :: U8_MAX; } - #if type == u16 { MIN :: 0; MAX :: U16_MAX; } - #if type == u32 { MIN :: 0; MAX :: U32_MAX; } - #if type == u64 { MIN :: 0; MAX :: U64_MAX; } - #if type == s8 { MIN :: S8_MIN; MAX :: S8_MAX; } - #if type == s16 { MIN :: S16_MIN; MAX :: S16_MAX; } - #if type == s32 { MIN :: S32_MIN; MAX :: S32_MAX; } - #if type == s64 { MIN :: S64_MIN; MAX :: S64_MAX; } - - NUM_TESTS :: 50000; - DATA_SIZE_BITS :: 64*1024*8; - #if type == s8 || type == u8 then - DATA_SIZE :: DATA_SIZE_BITS/8; - else #if type == s16 || type == u16 then - DATA_SIZE :: DATA_SIZE_BITS/16; - else #if type == s32 || type == u32 then - DATA_SIZE :: DATA_SIZE_BITS/32; - else #if type == s64 || type == u64 then - DATA_SIZE :: DATA_SIZE_BITS/64; - - best_gen := 0.0; - best_asm := 0.0; - numbers_x: [..] type; - numbers_y: [..] type; - array_reserve(*numbers_x, DATA_SIZE); - array_reserve(*numbers_y, DATA_SIZE); - - // Comment the line bellow to use the same "random" values. - random_seed(cast(u64)to_nanoseconds(current_time_monotonic())); - - for 0..DATA_SIZE-1 { - x := cast(type) random_get_within_range(xx MIN, xx MAX); - y := cast(type) random_get_within_range(xx MIN, xx MAX); - if y == 0 && operation == "div" { - y = 1; - } - array_add(*numbers_x, x); - array_add(*numbers_y, y); - } - - for 0..NUM_TESTS-1 { - - r_gen: type = 0; - r_asm: type = 0; - - time_gen := current_time_monotonic(); - for idx: 0..DATA_SIZE-1 #insert #run replace("r_gen ^= OP(numbers_x[idx], numbers_y[idx], true);", "OP", operation); - time_gen = current_time_monotonic() - time_gen; - - time_asm := current_time_monotonic(); - for idx: 0..DATA_SIZE-1 #insert #run replace("r_asm ^= OP(numbers_x[idx], numbers_y[idx]);", "OP", operation); - time_asm = current_time_monotonic() - time_asm; - - assert(r_gen == r_asm); - - perf_gen := cast(float)DATA_SIZE/cast(float)to_nanoseconds(time_gen); - perf_asm := cast(float)DATA_SIZE/cast(float)to_nanoseconds(time_asm); - best_gen = max(best_gen, perf_gen); - best_asm = max(best_asm, perf_asm); - } - - tmp_context := context; - push_context tmp_context { - ff := *context.print_style.default_format_float; - ff.zero_removal = .NO; - ff.width = 7; - ff.trailing_width = 2; - - fi := *context.print_style.default_format_int; - fi.minimum_digits = 3; - - if print_result { - if type == s8 || type == u8 write_string(" "); - print("% | % | % | %\n", type, best_gen, best_asm, cast(int)(100*best_asm/best_gen)); - } - } - return best_gen, best_asm; - } - - write_strings( - " | (ops / nsec) |\n", - " T | generic | x64 asm | %\n" - ); - - write_strings( - "--- | ----------------- | ---\n", - " | add |\n" - ); - performance_test("add", u8); - performance_test("add", u16); - performance_test("add", u32); - performance_test("add", u64); - performance_test("add", s8); - performance_test("add", s16); - performance_test("add", s32); - performance_test("add", s64); - - write_strings( - "--- | ----------------- | ---\n", - " | sub |\n" - ); - performance_test("sub", u8); - performance_test("sub", u16); - performance_test("sub", u32); - performance_test("sub", u64); - performance_test("sub", s8); - performance_test("sub", s16); - performance_test("sub", s32); - performance_test("sub", s64); - - write_strings( - "--- | ----------------- | ---\n", - " | mul |\n" - ); - performance_test("mul", u8); - performance_test("mul", u16); - performance_test("mul", u32); - performance_test("mul", u64); - performance_test("mul", s8); - performance_test("mul", s16); - performance_test("mul", s32); - performance_test("mul", s64); - - write_strings( - "--- | ----------------- | ---\n", - " | div |\n" - ); - performance_test("div", u8); - performance_test("div", u16); - performance_test("div", u32); - performance_test("div", u64); - performance_test("div", s8); - performance_test("div", s16); - performance_test("div", s32); - performance_test("div", s64); -} diff --git a/modules/Integer_Saturating_Arithmetic.jai b/modules/Integer_Saturating_Arithmetic.jai deleted file mode 100644 index 74643e0..0000000 --- a/modules/Integer_Saturating_Arithmetic.jai +++ /dev/null @@ -1,416 +0,0 @@ -// Integer saturating arighmetic (with assembly branch-free procedures for x64 - expecting signed values in two's complement). - -#import "Basic"; -#import "Math"; -#import "String"; - - -INTEGER_ARITHMETIC_TYPES_CHECK :: #string DONE - type_info_x := cast(*Type_Info)Tx; - type_info_y := cast(*Type_Info)Ty; - if type_info_x.type != .INTEGER || type_info_y.type != .INTEGER return false, "Non integers values passed."; - tx := cast(*Type_Info_Integer)type_info_x; - ty := cast(*Type_Info_Integer)type_info_y; - - largest_type := - ifx tx.runtime_size > ty.runtime_size then Tx else - ifx ty.runtime_size > tx.runtime_size then Ty else - ifx tx.signed == ty.signed then Tx else - void; - - // Only allow to add different signedness values if largest type is the signed one (as in JAI). - if tx.signed == ty.signed { - Tx = largest_type; - Ty = largest_type; - Tr = largest_type; - } - else if tx.signed && Tx == largest_type { - Ty = largest_type; - Tr = largest_type; - } - else if ty.signed && Ty == largest_type { - Tx = largest_type; - Tr = largest_type; - } - else return false, "Number signedness mismatch."; - - return true; -DONE - -add :: (x: $Tx, y: $Ty, $USE_GENERIC: bool = false) -> result: $Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } -{ - - #if USE_GENERIC || CPU != .X64 { - - #if Tr == s8 || Tr == s16 || Tr == s32 || Tr == s64 { - - #if Tr == s8 { MAX :: S8_MAX; MIN :: S8_MIN; } - #if Tr == s16 { MAX :: S16_MAX; MIN :: S16_MIN; } - #if Tr == s32 { MAX :: S32_MAX; MIN :: S32_MIN; } - #if Tr == s64 { MAX :: S64_MAX; MIN :: S64_MIN; } - - if (y > 0 && x > MAX - y) then return MAX, true; - if (y < 0 && x < MIN - y) then return MIN, true; - - } else { - - #if Tr == u8 { MAX :: U8_MAX; } - #if Tr == u16 { MAX :: U16_MAX; } - #if Tr == u32 { MAX :: U32_MAX; } - #if Tr == u64 { MAX :: U64_MAX; } - - if (x > MAX - y) then return MAX, true; - - } - - return x + y, false; - - } else { - - result: Tr = ---; - saturated: bool = ---; - - - ADD_SIGNED_ASM :: #string DONE - #asm { - mov result, -1; // Pre-set result with signed maximum (set all bits... - shr.SIZE result, 1; // ...then, clear MSB). - bt x, SIGN_BIT; // Test sign bit (affect CF). - adc result, 0; // Overflow signed maximum to signed minimum if CF is set. - - add.SIZE x, y; // Add values (affect OF). - seto saturated; // Set saturated flag if OF. - cmovno result, x; // Move add-result to result if NOT OF. - } - DONE - - #if Tr == s8 - #insert #run replace(replace(ADD_SIGNED_ASM, ".SIZE", ".b"), "SIGN_BIT", "7"); - #if Tr == s16 - #insert #run replace(replace(ADD_SIGNED_ASM, ".SIZE", ".w"), "SIGN_BIT", "15"); - #if Tr == s32 - #insert #run replace(replace(ADD_SIGNED_ASM, ".SIZE", ".d"), "SIGN_BIT", "31"); - #if Tr == s64 - #insert #run replace(replace(ADD_SIGNED_ASM, ".SIZE", ".q"), "SIGN_BIT", "63"); - - - ADD_UNSIGNED_ASM :: #string DONE - #asm { - mov result, -1; // Pre-set result with unsigned maximum. - add.SIZE x, y; // Add values (affect CF). - setc saturated; // Set saturated flag if CF. - cmovnc result, x; // Move add-result to result if NOT CF. - } - DONE - - #if Tr == u8 - #insert #run replace(ADD_UNSIGNED_ASM, ".SIZE", ".b"); - #if Tr == u16 - #insert #run replace(ADD_UNSIGNED_ASM, ".SIZE", ".w"); - #if Tr == u32 - #insert #run replace(ADD_UNSIGNED_ASM, ".SIZE", ".d"); - #if Tr == u64 - #insert #run replace(ADD_UNSIGNED_ASM, ".SIZE", ".q"); - - - return result, saturated; - - } -} - -sub :: (x: $Tx, y: $Ty, $USE_GENERIC: bool = false) -> result: $Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } -{ - - #if USE_GENERIC || CPU != .X64 { - - #if Tr == s8 || Tr == s16 || Tr == s32 || Tr == s64 { - - #if Tr == s8 { MAX :: S8_MAX; MIN :: S8_MIN; } - #if Tr == s16 { MAX :: S16_MAX; MIN :: S16_MIN; } - #if Tr == s32 { MAX :: S32_MAX; MIN :: S32_MIN; } - #if Tr == s64 { MAX :: S64_MAX; MIN :: S64_MIN; } - - if (y < 0 && x > MAX + y) then return MAX, true; - if (y > 0 && x < MIN + y) then return MIN, true; - - } else { - - if (y > x) then return 0, true; - - } - - return x - y, false; - - } else { - - result: Tr = ---; - saturated: bool = ---; - - - SUB_SIGNED_ASM :: #string DONE - #asm { - mov result, -1; // Pre-set result with signed maximum (set all bits... - shr.SIZE result, 1; // ...then, clear MSB). - bt x, SIGN_BIT; // Test signal bit (affect CF). - adc result, 0; // Overflow signed maximum to signed minimum if CF is set. - - sub.SIZE x, y; // Subtract values (affect OF). - seto saturated; // Set saturated flag if OF. - cmovno result, x; // Move subtract-result to result if NOT OF. - } - DONE - - #if Tr == s8 - #insert #run replace(replace(SUB_SIGNED_ASM, ".SIZE", ".b"), "SIGN_BIT", "7"); - #if Tr == s16 - #insert #run replace(replace(SUB_SIGNED_ASM, ".SIZE", ".w"), "SIGN_BIT", "15"); - #if Tr == s32 - #insert #run replace(replace(SUB_SIGNED_ASM, ".SIZE", ".d"), "SIGN_BIT", "31"); - #if Tr == s64 - #insert #run replace(replace(SUB_SIGNED_ASM, ".SIZE", ".q"), "SIGN_BIT", "63"); - - - SUB_UNSIGNED_ASM :: #string DONE - #asm { - xor result, result; // Pre-set result with usigned minimum (zero). - sub.SIZE x, y; // Subtract values (affect CF). - setc saturated; // Set saturated flag if CF. - cmovnc result, x; // Move subtract-result to result if NOT CF. - } - DONE - - #if Tr == u8 - #insert #run replace(SUB_UNSIGNED_ASM, ".SIZE", ".b"); - #if Tr == u16 - #insert #run replace(SUB_UNSIGNED_ASM, ".SIZE", ".w"); - #if Tr == u32 - #insert #run replace(SUB_UNSIGNED_ASM, ".SIZE", ".d"); - #if Tr == u64 - #insert #run replace(SUB_UNSIGNED_ASM, ".SIZE", ".q"); - - - return result, saturated; - - } - -} - -mul :: (x: $Tx, y: $Ty, $USE_GENERIC: bool = false) -> result: $Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } -{ - - #if USE_GENERIC || CPU != .X64 { - - #if Tr == s8 || Tr == s16 || Tr == s32 || Tr == s64 { - - #if Tr == s8 { MAX :: S8_MAX; MIN :: S8_MIN; } - #if Tr == s16 { MAX :: S16_MAX; MIN :: S16_MIN; } - #if Tr == s32 { MAX :: S32_MAX; MIN :: S32_MIN; } - #if Tr == s64 { MAX :: S64_MAX; MIN :: S64_MIN; } - - if x == 0 || y == 0 then return 0, false; - if x > 0 && y > 0 && x > MAX / y then return MAX, true; - if x < 0 && y < 0 && x < MAX / y then return MAX, true; - if (y < 0 && x > 0 && y < MIN / x) || (x < 0 && y > 0 && x < MIN / y) then return MIN, true; - - } else { - - #if Tr == u8 { MAX :: U8_MAX; } - #if Tr == u16 { MAX :: U16_MAX; } - #if Tr == u32 { MAX :: U32_MAX; } - #if Tr == u64 { MAX :: U64_MAX; } - - if x == 0 || y == 0 then return 0, false; - if x > MAX / y then return MAX, true; - - } - - return x * y, false; - - } else { - - result: Tr = ---; - saturated: bool = ---; - - MUL_SIGNED_ASM :: #string DONE - #asm { - // Using two copies of the x value (x_, sign) seems to be a bit faster (not sure why). - mov x_: gpr === a, x; // Pin copy of x value to register A. - - mov result, -1; // Pre-set result with signed maximum (set all bits... - shr.SIZE result, 1; // ...then, clear MSB). - mov sign:, x; // Use copy of x value. - xor sign, y; // Calculate result signal bit using xor. - bt sign, SIGN_BIT; // Test signal bit (affect CF). - adc result, 0; // Overflow signed maximum to signed minimum if CF is set. - - imul.SIZE x_, y; // Multiply values (affect OF). - seto saturated; // Set saturated flag if OF. - cmovno result, x_; // Move multiply-result to result if NOT OF. - } - DONE - - #if Tr == s8 - #insert #run replace(replace(MUL_SIGNED_ASM, ".SIZE", ".b"), "SIGN_BIT", "7"); - #if Tr == s16 - #insert #run replace(replace(MUL_SIGNED_ASM, ".SIZE", ".w"), "SIGN_BIT", "15"); - #if Tr == s32 - #insert #run replace(replace(MUL_SIGNED_ASM, ".SIZE", ".d"), "SIGN_BIT", "31"); - #if Tr == s64 - #insert #run replace(replace(MUL_SIGNED_ASM, ".SIZE", ".q"), "SIGN_BIT", "63"); - - - MUL_UNSIGNED_ASM :: #string DONE - #asm { - result === a; // Pin result to register A. - - mov result, x; // Move value x to result. - mul.SIZE reg_d:, result, y; // Multiply values (affect CF). - setc saturated; // Set saturated flag if CF. - sbb mask:, mask; // If CF: mask = -1 (all bits set); else: mask = 0. - or result, mask; // If CF was set, then result will be set to unsigned maximum (all bits set). - } - DONE - - #if Tr == u8 - #insert #run replace(replace(MUL_UNSIGNED_ASM, ".SIZE", ".b"), "reg_d:,", ""); // For 8bits mul, we do not need D register. - #if Tr == u16 - #insert #run replace(MUL_UNSIGNED_ASM, ".SIZE", ".w"); - #if Tr == u32 - #insert #run replace(MUL_UNSIGNED_ASM, ".SIZE", ".d"); - #if Tr == u64 - #insert #run replace(MUL_UNSIGNED_ASM, ".SIZE", ".q"); - - - return result, saturated; - - } -} - -div :: (x: $Tx, y: $Ty, $USE_GENERIC: bool = false) -> result: $Tr, remainder: Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } -{ - - #if USE_GENERIC || CPU != .X64 { - - #if Tr == s8 || Tr == s16 || Tr == s32 || Tr == s64 { - - #if Tr == s8 { MAX :: S8_MAX; MIN :: S8_MIN; } - #if Tr == s16 { MAX :: S16_MAX; MIN :: S16_MIN; } - #if Tr == s32 { MAX :: S32_MAX; MIN :: S32_MIN; } - #if Tr == s64 { MAX :: S64_MAX; MIN :: S64_MIN; } - - if x == MIN && y == -1 then return MAX, -1, true; - - } - - result := x / y; - remainder := x - (y * result); - return result, remainder, false; - - } else { - - result: Tr = ---; - remainder: Tr = ---; - saturated: bool = ---; - - DIV_SIGNED_ASM :: #string DONE - #asm { - result === a; // Pin result to register A (to be used as dividend on idiv). - remainder === d; // Pin remainder to register D. - - xor saturated, saturated; // Clear saturated. - - // Detect div(MIN/-1) and flag it on ZF. - mov t_dividend:, -1; // Pre-set t_dividend with signed minimum (set all bits... - shr.SIZE t_dividend, 1; // ...then, clear MSB... - not t_dividend; // ...then, negate to obtain MSB set and all other bits cleared). - // - mov limit:, t_dividend; // Keep copy of signed minimum on limit. - add limit, 1; // Set limit as signed minimum + 1. - // - xor.SIZE t_dividend, x; // Clear dividend if x value is equal to signed minimum. - // - mov t_divisor:, -1; // Pre-set test_divisor with -1. - xor.SIZE t_divisor, y; // Clear test_divisor if y value is equal to -1. - // - or.SIZE t_dividend, t_divisor; // Or t_dividend with t_divisor (affect ZF). - - setz saturated; // Set saturated flag if ZF. - mov result, x; // Copy x value to result (dividend). - cmovz result, limit; // If ZF: copy limit (signed minimum + 1) to result (dividend). - - DIVIDE_PLACEHOLDER - - sub.SIZE remainder, saturated; // If saturated: remainder = 0 - 1; otherwise: remainder = x - 0. - } - DONE - - DIV_SIGNED_CALC_8BITS :: #string DONE - cbw result; // Prepare dividend high bits (sign-extend). - idiv.SIZE result, y; // Divide values. - mov remainder, result; // Extract remainder from result's high bits. - sar remainder, 8; // Shift remainder from high to low bits. - DONE - - DIV_SIGNED_CALC_16BITS :: #string DONE - cwd remainder, result; // Prepare dividend high bits (sign-extend). - idiv.SIZE remainder, result, y; // Divide values. - DONE - - DIV_SIGNED_CALC_32BITS :: #string DONE - cdq remainder, result; // Prepare dividend high bits (sign-extend). - idiv.SIZE remainder, result, y; // Divide values. - DONE - - DIV_SIGNED_CALC_64BITS :: #string DONE - cqo remainder, result; // Prepare dividend high bits (sign-extend). - idiv.SIZE remainder, result, y; // Divide values. - DONE - - #if Tr == s8 - #insert #run replace(replace(DIV_SIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_SIGNED_CALC_8BITS), ".SIZE", ".b"); - #if Tr == s16 - #insert #run replace(replace(DIV_SIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_SIGNED_CALC_16BITS), ".SIZE", ".w"); - #if Tr == s32 - #insert #run replace(replace(DIV_SIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_SIGNED_CALC_32BITS), ".SIZE", ".d"); - #if Tr == s64 - #insert #run replace(replace(DIV_SIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_SIGNED_CALC_64BITS), ".SIZE", ".q"); - - - DIV_UNSIGNED_ASM :: #string DONE - #asm { - result === a; // Pin result to register A. - remainder === d; // Pin remainder to register D. - - xor result, result; // Clear result. - xor remainder, remainder; // Clear remainder (required when used as dividend's high bits). - xor saturated, saturated; // Clear saturated (unsigned division never saturates). - mov result, x; // Copy x value to result. - - DIVIDE_PLACEHOLDER - } - DONE - - DIV_UNSIGNED_CALC_8BITS :: #string DONE - div.SIZE result, y; // Divide values. - mov remainder, result; // Extract remainder from result's high bits. - sar remainder, 8; // Shift remainder from high to low bits. - DONE - - DIV_UNSIGNED_CALC :: #string DONE - div.SIZE remainder, result, y; // Divide values. - DONE - - #if Tr == u8 - #insert #run replace(replace(DIV_UNSIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_UNSIGNED_CALC_8BITS), ".SIZE", ".b"); - #if Tr == u16 - #insert #run replace(replace(DIV_UNSIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_UNSIGNED_CALC), ".SIZE", ".w"); - #if Tr == u32 - #insert #run replace(replace(DIV_UNSIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_UNSIGNED_CALC), ".SIZE", ".d"); - #if Tr == u64 - #insert #run replace(replace(DIV_UNSIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_UNSIGNED_CALC), ".SIZE", ".q"); - - - return result, remainder, saturated; - - } -} diff --git a/modules/Saturation/module.jai b/modules/Saturation/module.jai new file mode 100644 index 0000000..74643e0 --- /dev/null +++ b/modules/Saturation/module.jai @@ -0,0 +1,416 @@ +// Integer saturating arighmetic (with assembly branch-free procedures for x64 - expecting signed values in two's complement). + +#import "Basic"; +#import "Math"; +#import "String"; + + +INTEGER_ARITHMETIC_TYPES_CHECK :: #string DONE + type_info_x := cast(*Type_Info)Tx; + type_info_y := cast(*Type_Info)Ty; + if type_info_x.type != .INTEGER || type_info_y.type != .INTEGER return false, "Non integers values passed."; + tx := cast(*Type_Info_Integer)type_info_x; + ty := cast(*Type_Info_Integer)type_info_y; + + largest_type := + ifx tx.runtime_size > ty.runtime_size then Tx else + ifx ty.runtime_size > tx.runtime_size then Ty else + ifx tx.signed == ty.signed then Tx else + void; + + // Only allow to add different signedness values if largest type is the signed one (as in JAI). + if tx.signed == ty.signed { + Tx = largest_type; + Ty = largest_type; + Tr = largest_type; + } + else if tx.signed && Tx == largest_type { + Ty = largest_type; + Tr = largest_type; + } + else if ty.signed && Ty == largest_type { + Tx = largest_type; + Tr = largest_type; + } + else return false, "Number signedness mismatch."; + + return true; +DONE + +add :: (x: $Tx, y: $Ty, $USE_GENERIC: bool = false) -> result: $Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } +{ + + #if USE_GENERIC || CPU != .X64 { + + #if Tr == s8 || Tr == s16 || Tr == s32 || Tr == s64 { + + #if Tr == s8 { MAX :: S8_MAX; MIN :: S8_MIN; } + #if Tr == s16 { MAX :: S16_MAX; MIN :: S16_MIN; } + #if Tr == s32 { MAX :: S32_MAX; MIN :: S32_MIN; } + #if Tr == s64 { MAX :: S64_MAX; MIN :: S64_MIN; } + + if (y > 0 && x > MAX - y) then return MAX, true; + if (y < 0 && x < MIN - y) then return MIN, true; + + } else { + + #if Tr == u8 { MAX :: U8_MAX; } + #if Tr == u16 { MAX :: U16_MAX; } + #if Tr == u32 { MAX :: U32_MAX; } + #if Tr == u64 { MAX :: U64_MAX; } + + if (x > MAX - y) then return MAX, true; + + } + + return x + y, false; + + } else { + + result: Tr = ---; + saturated: bool = ---; + + + ADD_SIGNED_ASM :: #string DONE + #asm { + mov result, -1; // Pre-set result with signed maximum (set all bits... + shr.SIZE result, 1; // ...then, clear MSB). + bt x, SIGN_BIT; // Test sign bit (affect CF). + adc result, 0; // Overflow signed maximum to signed minimum if CF is set. + + add.SIZE x, y; // Add values (affect OF). + seto saturated; // Set saturated flag if OF. + cmovno result, x; // Move add-result to result if NOT OF. + } + DONE + + #if Tr == s8 + #insert #run replace(replace(ADD_SIGNED_ASM, ".SIZE", ".b"), "SIGN_BIT", "7"); + #if Tr == s16 + #insert #run replace(replace(ADD_SIGNED_ASM, ".SIZE", ".w"), "SIGN_BIT", "15"); + #if Tr == s32 + #insert #run replace(replace(ADD_SIGNED_ASM, ".SIZE", ".d"), "SIGN_BIT", "31"); + #if Tr == s64 + #insert #run replace(replace(ADD_SIGNED_ASM, ".SIZE", ".q"), "SIGN_BIT", "63"); + + + ADD_UNSIGNED_ASM :: #string DONE + #asm { + mov result, -1; // Pre-set result with unsigned maximum. + add.SIZE x, y; // Add values (affect CF). + setc saturated; // Set saturated flag if CF. + cmovnc result, x; // Move add-result to result if NOT CF. + } + DONE + + #if Tr == u8 + #insert #run replace(ADD_UNSIGNED_ASM, ".SIZE", ".b"); + #if Tr == u16 + #insert #run replace(ADD_UNSIGNED_ASM, ".SIZE", ".w"); + #if Tr == u32 + #insert #run replace(ADD_UNSIGNED_ASM, ".SIZE", ".d"); + #if Tr == u64 + #insert #run replace(ADD_UNSIGNED_ASM, ".SIZE", ".q"); + + + return result, saturated; + + } +} + +sub :: (x: $Tx, y: $Ty, $USE_GENERIC: bool = false) -> result: $Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } +{ + + #if USE_GENERIC || CPU != .X64 { + + #if Tr == s8 || Tr == s16 || Tr == s32 || Tr == s64 { + + #if Tr == s8 { MAX :: S8_MAX; MIN :: S8_MIN; } + #if Tr == s16 { MAX :: S16_MAX; MIN :: S16_MIN; } + #if Tr == s32 { MAX :: S32_MAX; MIN :: S32_MIN; } + #if Tr == s64 { MAX :: S64_MAX; MIN :: S64_MIN; } + + if (y < 0 && x > MAX + y) then return MAX, true; + if (y > 0 && x < MIN + y) then return MIN, true; + + } else { + + if (y > x) then return 0, true; + + } + + return x - y, false; + + } else { + + result: Tr = ---; + saturated: bool = ---; + + + SUB_SIGNED_ASM :: #string DONE + #asm { + mov result, -1; // Pre-set result with signed maximum (set all bits... + shr.SIZE result, 1; // ...then, clear MSB). + bt x, SIGN_BIT; // Test signal bit (affect CF). + adc result, 0; // Overflow signed maximum to signed minimum if CF is set. + + sub.SIZE x, y; // Subtract values (affect OF). + seto saturated; // Set saturated flag if OF. + cmovno result, x; // Move subtract-result to result if NOT OF. + } + DONE + + #if Tr == s8 + #insert #run replace(replace(SUB_SIGNED_ASM, ".SIZE", ".b"), "SIGN_BIT", "7"); + #if Tr == s16 + #insert #run replace(replace(SUB_SIGNED_ASM, ".SIZE", ".w"), "SIGN_BIT", "15"); + #if Tr == s32 + #insert #run replace(replace(SUB_SIGNED_ASM, ".SIZE", ".d"), "SIGN_BIT", "31"); + #if Tr == s64 + #insert #run replace(replace(SUB_SIGNED_ASM, ".SIZE", ".q"), "SIGN_BIT", "63"); + + + SUB_UNSIGNED_ASM :: #string DONE + #asm { + xor result, result; // Pre-set result with usigned minimum (zero). + sub.SIZE x, y; // Subtract values (affect CF). + setc saturated; // Set saturated flag if CF. + cmovnc result, x; // Move subtract-result to result if NOT CF. + } + DONE + + #if Tr == u8 + #insert #run replace(SUB_UNSIGNED_ASM, ".SIZE", ".b"); + #if Tr == u16 + #insert #run replace(SUB_UNSIGNED_ASM, ".SIZE", ".w"); + #if Tr == u32 + #insert #run replace(SUB_UNSIGNED_ASM, ".SIZE", ".d"); + #if Tr == u64 + #insert #run replace(SUB_UNSIGNED_ASM, ".SIZE", ".q"); + + + return result, saturated; + + } + +} + +mul :: (x: $Tx, y: $Ty, $USE_GENERIC: bool = false) -> result: $Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } +{ + + #if USE_GENERIC || CPU != .X64 { + + #if Tr == s8 || Tr == s16 || Tr == s32 || Tr == s64 { + + #if Tr == s8 { MAX :: S8_MAX; MIN :: S8_MIN; } + #if Tr == s16 { MAX :: S16_MAX; MIN :: S16_MIN; } + #if Tr == s32 { MAX :: S32_MAX; MIN :: S32_MIN; } + #if Tr == s64 { MAX :: S64_MAX; MIN :: S64_MIN; } + + if x == 0 || y == 0 then return 0, false; + if x > 0 && y > 0 && x > MAX / y then return MAX, true; + if x < 0 && y < 0 && x < MAX / y then return MAX, true; + if (y < 0 && x > 0 && y < MIN / x) || (x < 0 && y > 0 && x < MIN / y) then return MIN, true; + + } else { + + #if Tr == u8 { MAX :: U8_MAX; } + #if Tr == u16 { MAX :: U16_MAX; } + #if Tr == u32 { MAX :: U32_MAX; } + #if Tr == u64 { MAX :: U64_MAX; } + + if x == 0 || y == 0 then return 0, false; + if x > MAX / y then return MAX, true; + + } + + return x * y, false; + + } else { + + result: Tr = ---; + saturated: bool = ---; + + MUL_SIGNED_ASM :: #string DONE + #asm { + // Using two copies of the x value (x_, sign) seems to be a bit faster (not sure why). + mov x_: gpr === a, x; // Pin copy of x value to register A. + + mov result, -1; // Pre-set result with signed maximum (set all bits... + shr.SIZE result, 1; // ...then, clear MSB). + mov sign:, x; // Use copy of x value. + xor sign, y; // Calculate result signal bit using xor. + bt sign, SIGN_BIT; // Test signal bit (affect CF). + adc result, 0; // Overflow signed maximum to signed minimum if CF is set. + + imul.SIZE x_, y; // Multiply values (affect OF). + seto saturated; // Set saturated flag if OF. + cmovno result, x_; // Move multiply-result to result if NOT OF. + } + DONE + + #if Tr == s8 + #insert #run replace(replace(MUL_SIGNED_ASM, ".SIZE", ".b"), "SIGN_BIT", "7"); + #if Tr == s16 + #insert #run replace(replace(MUL_SIGNED_ASM, ".SIZE", ".w"), "SIGN_BIT", "15"); + #if Tr == s32 + #insert #run replace(replace(MUL_SIGNED_ASM, ".SIZE", ".d"), "SIGN_BIT", "31"); + #if Tr == s64 + #insert #run replace(replace(MUL_SIGNED_ASM, ".SIZE", ".q"), "SIGN_BIT", "63"); + + + MUL_UNSIGNED_ASM :: #string DONE + #asm { + result === a; // Pin result to register A. + + mov result, x; // Move value x to result. + mul.SIZE reg_d:, result, y; // Multiply values (affect CF). + setc saturated; // Set saturated flag if CF. + sbb mask:, mask; // If CF: mask = -1 (all bits set); else: mask = 0. + or result, mask; // If CF was set, then result will be set to unsigned maximum (all bits set). + } + DONE + + #if Tr == u8 + #insert #run replace(replace(MUL_UNSIGNED_ASM, ".SIZE", ".b"), "reg_d:,", ""); // For 8bits mul, we do not need D register. + #if Tr == u16 + #insert #run replace(MUL_UNSIGNED_ASM, ".SIZE", ".w"); + #if Tr == u32 + #insert #run replace(MUL_UNSIGNED_ASM, ".SIZE", ".d"); + #if Tr == u64 + #insert #run replace(MUL_UNSIGNED_ASM, ".SIZE", ".q"); + + + return result, saturated; + + } +} + +div :: (x: $Tx, y: $Ty, $USE_GENERIC: bool = false) -> result: $Tr, remainder: Tr, saturated: bool #modify { #insert INTEGER_ARITHMETIC_TYPES_CHECK; } +{ + + #if USE_GENERIC || CPU != .X64 { + + #if Tr == s8 || Tr == s16 || Tr == s32 || Tr == s64 { + + #if Tr == s8 { MAX :: S8_MAX; MIN :: S8_MIN; } + #if Tr == s16 { MAX :: S16_MAX; MIN :: S16_MIN; } + #if Tr == s32 { MAX :: S32_MAX; MIN :: S32_MIN; } + #if Tr == s64 { MAX :: S64_MAX; MIN :: S64_MIN; } + + if x == MIN && y == -1 then return MAX, -1, true; + + } + + result := x / y; + remainder := x - (y * result); + return result, remainder, false; + + } else { + + result: Tr = ---; + remainder: Tr = ---; + saturated: bool = ---; + + DIV_SIGNED_ASM :: #string DONE + #asm { + result === a; // Pin result to register A (to be used as dividend on idiv). + remainder === d; // Pin remainder to register D. + + xor saturated, saturated; // Clear saturated. + + // Detect div(MIN/-1) and flag it on ZF. + mov t_dividend:, -1; // Pre-set t_dividend with signed minimum (set all bits... + shr.SIZE t_dividend, 1; // ...then, clear MSB... + not t_dividend; // ...then, negate to obtain MSB set and all other bits cleared). + // + mov limit:, t_dividend; // Keep copy of signed minimum on limit. + add limit, 1; // Set limit as signed minimum + 1. + // + xor.SIZE t_dividend, x; // Clear dividend if x value is equal to signed minimum. + // + mov t_divisor:, -1; // Pre-set test_divisor with -1. + xor.SIZE t_divisor, y; // Clear test_divisor if y value is equal to -1. + // + or.SIZE t_dividend, t_divisor; // Or t_dividend with t_divisor (affect ZF). + + setz saturated; // Set saturated flag if ZF. + mov result, x; // Copy x value to result (dividend). + cmovz result, limit; // If ZF: copy limit (signed minimum + 1) to result (dividend). + + DIVIDE_PLACEHOLDER + + sub.SIZE remainder, saturated; // If saturated: remainder = 0 - 1; otherwise: remainder = x - 0. + } + DONE + + DIV_SIGNED_CALC_8BITS :: #string DONE + cbw result; // Prepare dividend high bits (sign-extend). + idiv.SIZE result, y; // Divide values. + mov remainder, result; // Extract remainder from result's high bits. + sar remainder, 8; // Shift remainder from high to low bits. + DONE + + DIV_SIGNED_CALC_16BITS :: #string DONE + cwd remainder, result; // Prepare dividend high bits (sign-extend). + idiv.SIZE remainder, result, y; // Divide values. + DONE + + DIV_SIGNED_CALC_32BITS :: #string DONE + cdq remainder, result; // Prepare dividend high bits (sign-extend). + idiv.SIZE remainder, result, y; // Divide values. + DONE + + DIV_SIGNED_CALC_64BITS :: #string DONE + cqo remainder, result; // Prepare dividend high bits (sign-extend). + idiv.SIZE remainder, result, y; // Divide values. + DONE + + #if Tr == s8 + #insert #run replace(replace(DIV_SIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_SIGNED_CALC_8BITS), ".SIZE", ".b"); + #if Tr == s16 + #insert #run replace(replace(DIV_SIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_SIGNED_CALC_16BITS), ".SIZE", ".w"); + #if Tr == s32 + #insert #run replace(replace(DIV_SIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_SIGNED_CALC_32BITS), ".SIZE", ".d"); + #if Tr == s64 + #insert #run replace(replace(DIV_SIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_SIGNED_CALC_64BITS), ".SIZE", ".q"); + + + DIV_UNSIGNED_ASM :: #string DONE + #asm { + result === a; // Pin result to register A. + remainder === d; // Pin remainder to register D. + + xor result, result; // Clear result. + xor remainder, remainder; // Clear remainder (required when used as dividend's high bits). + xor saturated, saturated; // Clear saturated (unsigned division never saturates). + mov result, x; // Copy x value to result. + + DIVIDE_PLACEHOLDER + } + DONE + + DIV_UNSIGNED_CALC_8BITS :: #string DONE + div.SIZE result, y; // Divide values. + mov remainder, result; // Extract remainder from result's high bits. + sar remainder, 8; // Shift remainder from high to low bits. + DONE + + DIV_UNSIGNED_CALC :: #string DONE + div.SIZE remainder, result, y; // Divide values. + DONE + + #if Tr == u8 + #insert #run replace(replace(DIV_UNSIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_UNSIGNED_CALC_8BITS), ".SIZE", ".b"); + #if Tr == u16 + #insert #run replace(replace(DIV_UNSIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_UNSIGNED_CALC), ".SIZE", ".w"); + #if Tr == u32 + #insert #run replace(replace(DIV_UNSIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_UNSIGNED_CALC), ".SIZE", ".d"); + #if Tr == u64 + #insert #run replace(replace(DIV_UNSIGNED_ASM, "DIVIDE_PLACEHOLDER", DIV_UNSIGNED_CALC), ".SIZE", ".q"); + + + return result, remainder, saturated; + + } +} diff --git a/modules/Saturation/tests.jai b/modules/Saturation/tests.jai new file mode 100644 index 0000000..372d66d --- /dev/null +++ b/modules/Saturation/tests.jai @@ -0,0 +1,304 @@ +// Tests for integer saturating arighmetic procedures. + +#import "Basic"; +#import "Compiler"; +#import "Math"; +#import "String"; +#import "Saturation"; + +main :: () { + + write_strings( + "#=======================#\n", + "# Basic tests #\n" + ); + + test_op :: (operation: string, x: $Tx, y: $Ty, result: $Tr, type: Type, saturated: bool, remainder: Tr = 0) -> errors_found: int #expand { + + print_test_call :: (operation: string) -> string { + str: string = ---; + if operation != "div" { + TEST_CALL :: #string DONE + t_result, t_saturated := OP(cast(Tx)x, cast(Ty)y); + if result != t_result print("%_%(%, %) = %0%0\n", operation, type, x, y, result, ifx saturated then " : saturated"); + DONE + str = replace(TEST_CALL, "OP", operation); + } else { + TEST_CALL :: #string DONE + t_result, t_remainder, t_saturated := OP(cast(Tx)x, cast(Ty)y); + if result != t_result print("%_%(%, %) = % + %0%0\n", operation, type, x, y, result, remainder, ifx saturated then " : saturated"); + DONE + str = replace(TEST_CALL, "OP", operation); + } + return str; + } + + #insert #run print_test_call(operation); + + errors := 0; + if result != t_result { errors += 1; print(" > incorrect result value: got % expected %\n", t_result, result); }; + if type != type_of(t_result) { errors += 1; print(" > incorrect result type: got % expected %\n", type_of(t_result), type); }; + if saturated != t_saturated { errors += 1; print(" > incorrect saturated flag: got % expected %\n", t_saturated, saturated); }; + #if operation == "div" { + if remainder != t_remainder { errors += 1; print(" > incorrect remainder value: got % expected %\n", t_remainder, remainder); }; + } + return errors; + } + + errors := 0; + + // Test signed add. + errors += test_op("add", cast( s8) S8_MAX, cast( s8)1, S8_MAX, s8, true); + errors += test_op("add", cast(s16)S16_MAX, cast( u8)1, S16_MAX, s16, true); + errors += test_op("add", cast(s32)S32_MAX, cast(s32)1, S32_MAX, s32, true); + errors += test_op("add", cast(s64)S64_MAX, cast(u32)1, S64_MAX, s64, true); + + errors += test_op("add", cast( s8) S8_MAX, cast( s8) S8_MIN, -1, s8, false); + errors += test_op("add", cast(s16)S16_MAX, cast(s16)S16_MIN, -1, s16, false); + errors += test_op("add", cast(s32)S32_MAX, cast(s32)S32_MIN, -1, s32, false); + errors += test_op("add", cast(s64)S64_MAX, cast(s64)S64_MIN, -1, s64, false); + + // Test unsigned add. + errors += test_op("add", cast( u8) U8_MAX, cast( u8)1, U8_MAX, u8, true); + errors += test_op("add", cast(u16)U16_MAX, cast(u16)1, U16_MAX, u16, true); + errors += test_op("add", cast(u32)U32_MAX, cast(u32)1, U32_MAX, u32, true); + errors += test_op("add", cast(u64)U64_MAX, cast(u64)1, U64_MAX, u64, true); + + errors += test_op("add", cast( u8) U8_MAX, cast( u8)0, U8_MAX, u8, false); + errors += test_op("add", cast(u16)U16_MAX, cast(u16)0, U16_MAX, u16, false); + errors += test_op("add", cast(u32)U32_MAX, cast(u32)0, U32_MAX, u32, false); + errors += test_op("add", cast(u64)U64_MAX, cast(u64)0, U64_MAX, u64, false); + + // Test signed sub. + errors += test_op("sub", cast( s8) S8_MIN, cast( s8)1, S8_MIN, s8, true); + errors += test_op("sub", cast(s16)S16_MIN, cast( u8)1, S16_MIN, s16, true); + errors += test_op("sub", cast(s32)S32_MIN, cast(s32)1, S32_MIN, s32, true); + errors += test_op("sub", cast(s64)S64_MIN, cast(u32)1, S64_MIN, s64, true); + + errors += test_op("sub", cast( s8)-1, cast( s8) S8_MAX, S8_MIN, s8, false); + errors += test_op("sub", cast(s16)-1, cast(s16)S16_MAX, S16_MIN, s16, false); + errors += test_op("sub", cast(s32)-1, cast(s32)S32_MAX, S32_MIN, s32, false); + errors += test_op("sub", cast(s64)-1, cast(s64)S64_MAX, S64_MIN, s64, false); + + // Test unsigned sub. + errors += test_op("sub", cast( u8)1, cast( u8) U8_MAX, 0, u8, true); + errors += test_op("sub", cast( u8)1, cast(u16)U16_MAX, 0, u16, true); + errors += test_op("sub", cast(u32)1, cast(u32)U32_MAX, 0, u32, true); + errors += test_op("sub", cast(u32)1, cast(u64)U64_MAX, 0, u64, true); + + errors += test_op("sub", cast( u8) U8_MAX, cast( u8)0, U8_MAX, u8, false); + errors += test_op("sub", cast(u16)U16_MAX, cast( u8)0, U16_MAX, u16, false); + errors += test_op("sub", cast(u32)U32_MAX, cast(u32)0, U32_MAX, u32, false); + errors += test_op("sub", cast(u64)U64_MAX, cast(u32)0, U64_MAX, u64, false); + + // Test signed mul. + errors += test_op("mul", cast( s8) S8_MIN, cast( s8)-1, S8_MAX, s8, true); + errors += test_op("mul", cast(s16)S16_MIN, cast( s8)-1, S16_MAX, s16, true); + errors += test_op("mul", cast(s32)S32_MIN, cast(s32)-1, S32_MAX, s32, true); + errors += test_op("mul", cast(s64)S64_MIN, cast(s32)-1, S64_MAX, s64, true); + + errors += test_op("mul", cast( s8) S8_MAX, cast( s8)-2, S8_MIN, s8, true); + errors += test_op("mul", cast(s16)S16_MAX, cast( s8)-2, S16_MIN, s16, true); + errors += test_op("mul", cast(s32)S32_MAX, cast(s32)-2, S32_MIN, s32, true); + errors += test_op("mul", cast(s64)S64_MAX, cast(s32)-2, S64_MIN, s64, true); + + errors += test_op("mul", cast( s8)-2, cast( s8) S8_MAX, S8_MIN, s8, true); + errors += test_op("mul", cast( s8)-2, cast(s16)S16_MAX, S16_MIN, s16, true); + errors += test_op("mul", cast(s32)-2, cast(s32)S32_MAX, S32_MIN, s32, true); + errors += test_op("mul", cast(s32)-2, cast(s64)S64_MAX, S64_MIN, s64, true); + + errors += test_op("mul", cast( s8) S8_MAX, cast( s8)2, S8_MAX, s8, true); + errors += test_op("mul", cast(s16)S16_MAX, cast( s8)2, S16_MAX, s16, true); + errors += test_op("mul", cast(s32)S32_MAX, cast(s32)2, S32_MAX, s32, true); + errors += test_op("mul", cast(s64)S64_MAX, cast(s32)2, S64_MAX, s64, true); + + errors += test_op("mul", cast( s8) S8_MAX, cast( s8)-1, -S8_MAX, s8, false); + errors += test_op("mul", cast(s16)S16_MAX, cast( s8)-1, -S16_MAX, s16, false); + errors += test_op("mul", cast(s32)S32_MAX, cast(s32)-1, -S32_MAX, s32, false); + errors += test_op("mul", cast(s64)S64_MAX, cast(s32)-1, -S64_MAX, s64, false); + + errors += test_op("mul", cast( s8) S8_MAX, cast( s8)0, 0, s8, false); + errors += test_op("mul", cast(s16)S16_MAX, cast( u8)0, 0, s16, false); + errors += test_op("mul", cast(s32)S32_MAX, cast(s32)0, 0, s32, false); + errors += test_op("mul", cast(s64)S64_MAX, cast(u32)0, 0, s64, false); + + // Test unsigned mul. + errors += test_op("mul", cast( u8) U8_MAX, cast( u8)1, U8_MAX, u8, false); + errors += test_op("mul", cast(u16)U16_MAX, cast( u8)1, U16_MAX, u16, false); + errors += test_op("mul", cast(u32)U32_MAX, cast(u32)1, U32_MAX, u32, false); + errors += test_op("mul", cast(u64)U64_MAX, cast(u32)1, U64_MAX, u64, false); + + errors += test_op("mul", cast( u8) U8_MAX, cast( u8)2, U8_MAX, u8, true); + errors += test_op("mul", cast(u16)U16_MAX, cast( u8)2, U16_MAX, u16, true); + errors += test_op("mul", cast(u32)U32_MAX, cast(u32)2, U32_MAX, u32, true); + errors += test_op("mul", cast(u64)U64_MAX, cast(u32)2, U64_MAX, u64, true); + + // Test signed div. + errors += test_op("div", cast( s8) S8_MIN, cast( s8)-1, S8_MAX, s8, true, -1); + errors += test_op("div", cast(s16)S16_MIN, cast( s8)-1, S16_MAX, s16, true, -1); + errors += test_op("div", cast(s32)S32_MIN, cast(s32)-1, S32_MAX, s32, true, -1); + errors += test_op("div", cast(s64)S64_MIN, cast(s32)-1, S64_MAX, s64, true, -1); + + errors += test_op("div", cast( s8) S8_MAX, cast( s8)-2, - S8_MAX/2, s8, false, 1); + errors += test_op("div", cast(s16)S16_MAX, cast( s8)-2, -S16_MAX/2, s16, false, 1); + errors += test_op("div", cast(s32)S32_MAX, cast(s32)-2, -S32_MAX/2, s32, false, 1); + errors += test_op("div", cast(s64)S64_MAX, cast(s32)-2, -S64_MAX/2, s64, false, 1); + + errors += test_op("div", cast( s8)15, cast( s8)5, 3, s8, false, 0); + errors += test_op("div", cast( u8)15, cast(s16)7, 2, s16, false, 1); + errors += test_op("div", cast(s16)15, cast(s32)13, 1, s32, false, 2); + errors += test_op("div", cast(u16)100, cast(s64)3, 33, s64, false, 1); + + // Test unsigned div. + errors += test_op("div", cast( u8) U8_MAX, cast( u8)2, U8_MAX/2, u8, false, 1); + errors += test_op("div", cast(u16)U16_MAX, cast( u8)2, U16_MAX/2, u16, false, 1); + errors += test_op("div", cast(u32)U32_MAX, cast(u32)2, U32_MAX/2, u32, false, 1); + errors += test_op("div", cast(u64)U64_MAX, cast(u32)2, U64_MAX/2, u64, false, 1); + + if errors > 0 print("# Found % %!\n", errors, ifx errors == 1 then "error" else "errors"); else print(" No errors found.\n"); + + write_strings( + "#=======================#\n", + "# Benchmarks #\n" + ); + + #import "Random"; + + performance_test :: ($operation: string, $type: Type, print_result: bool = true) -> ops_per_us_gen: float, ops_per_us_asm: float { + + #if type == u8 { MIN :: 0; MAX :: U8_MAX; } + #if type == u16 { MIN :: 0; MAX :: U16_MAX; } + #if type == u32 { MIN :: 0; MAX :: U32_MAX; } + #if type == u64 { MIN :: 0; MAX :: U64_MAX; } + #if type == s8 { MIN :: S8_MIN; MAX :: S8_MAX; } + #if type == s16 { MIN :: S16_MIN; MAX :: S16_MAX; } + #if type == s32 { MIN :: S32_MIN; MAX :: S32_MAX; } + #if type == s64 { MIN :: S64_MIN; MAX :: S64_MAX; } + + NUM_TESTS :: 50000; + DATA_SIZE_BITS :: 64*1024*8; + #if type == s8 || type == u8 then + DATA_SIZE :: DATA_SIZE_BITS/8; + else #if type == s16 || type == u16 then + DATA_SIZE :: DATA_SIZE_BITS/16; + else #if type == s32 || type == u32 then + DATA_SIZE :: DATA_SIZE_BITS/32; + else #if type == s64 || type == u64 then + DATA_SIZE :: DATA_SIZE_BITS/64; + + best_gen := 0.0; + best_asm := 0.0; + numbers_x: [..] type; + numbers_y: [..] type; + array_reserve(*numbers_x, DATA_SIZE); + array_reserve(*numbers_y, DATA_SIZE); + + // Comment the line bellow to use the same "random" values. + random_seed(cast(u64)to_nanoseconds(current_time_monotonic())); + + for 0..DATA_SIZE-1 { + x := cast(type) random_get_within_range(xx MIN, xx MAX); + y := cast(type) random_get_within_range(xx MIN, xx MAX); + if y == 0 && operation == "div" { + y = 1; + } + array_add(*numbers_x, x); + array_add(*numbers_y, y); + } + + for 0..NUM_TESTS-1 { + + r_gen: type = 0; + r_asm: type = 0; + + time_gen := current_time_monotonic(); + for idx: 0..DATA_SIZE-1 #insert #run replace("r_gen ^= OP(numbers_x[idx], numbers_y[idx], true);", "OP", operation); + time_gen = current_time_monotonic() - time_gen; + + time_asm := current_time_monotonic(); + for idx: 0..DATA_SIZE-1 #insert #run replace("r_asm ^= OP(numbers_x[idx], numbers_y[idx]);", "OP", operation); + time_asm = current_time_monotonic() - time_asm; + + assert(r_gen == r_asm); + + perf_gen := cast(float)DATA_SIZE/cast(float)to_nanoseconds(time_gen); + perf_asm := cast(float)DATA_SIZE/cast(float)to_nanoseconds(time_asm); + best_gen = max(best_gen, perf_gen); + best_asm = max(best_asm, perf_asm); + } + + tmp_context := context; + push_context tmp_context { + ff := *context.print_style.default_format_float; + ff.zero_removal = .NO; + ff.width = 7; + ff.trailing_width = 2; + + fi := *context.print_style.default_format_int; + fi.minimum_digits = 3; + + if print_result { + if type == s8 || type == u8 write_string(" "); + print("% | % | % | %\n", type, best_gen, best_asm, cast(int)(100*best_asm/best_gen)); + } + } + return best_gen, best_asm; + } + + write_strings( + " | (ops / nsec) |\n", + " T | generic | x64 asm | %\n" + ); + + write_strings( + "--- | ----------------- | ---\n", + " | add |\n" + ); + performance_test("add", u8); + performance_test("add", u16); + performance_test("add", u32); + performance_test("add", u64); + performance_test("add", s8); + performance_test("add", s16); + performance_test("add", s32); + performance_test("add", s64); + + write_strings( + "--- | ----------------- | ---\n", + " | sub |\n" + ); + performance_test("sub", u8); + performance_test("sub", u16); + performance_test("sub", u32); + performance_test("sub", u64); + performance_test("sub", s8); + performance_test("sub", s16); + performance_test("sub", s32); + performance_test("sub", s64); + + write_strings( + "--- | ----------------- | ---\n", + " | mul |\n" + ); + performance_test("mul", u8); + performance_test("mul", u16); + performance_test("mul", u32); + performance_test("mul", u64); + performance_test("mul", s8); + performance_test("mul", s16); + performance_test("mul", s32); + performance_test("mul", s64); + + write_strings( + "--- | ----------------- | ---\n", + " | div |\n" + ); + performance_test("div", u8); + performance_test("div", u16); + performance_test("div", u32); + performance_test("div", u64); + performance_test("div", s8); + performance_test("div", s16); + performance_test("div", s32); + performance_test("div", s64); +} diff --git a/modules/TUI/key_map.jai b/modules/TUI/key_map.jai index 7a074b2..f0754a7 100644 --- a/modules/TUI/key_map.jai +++ b/modules/TUI/key_map.jai @@ -8,10 +8,11 @@ setup_key_map :: () { /* This table was created/tested using the following terminals: - - g: gnome (terminal) + - g: gnome terminal - i: kitty - k: konsole - - l: linux (console) + - l: linux console + - w: windows terminal - x: xterm To signal modifier keys, a letter is appended after a + (plus sign): @@ -33,16 +34,16 @@ setup_key_map :: () { "#f1+Z" -> F1 + Shift + Alt + Ctrl + Super */ - // Up // g i k l x - table_set(*key_map, "\e[A", to_key("#up")); // + + + + + + // Up // g i k l w x + table_set(*key_map, "\e[A", to_key("#up")); // + + + + + + table_set(*key_map, "\e[1;1A", to_key("#up")); // - table_set(*key_map, "\e[1;2A", to_key("#up+$")); // + + + + - table_set(*key_map, "\e[1;3A", to_key("#up+a")); // + + + + - table_set(*key_map, "\e[1;4A", to_key("#up+A")); // + + + + - table_set(*key_map, "\e[1;5A", to_key("#up+c")); // + + + + - table_set(*key_map, "\e[1;6A", to_key("#up+C")); // + + + + - table_set(*key_map, "\e[1;7A", to_key("#up+w")); // + + + + - table_set(*key_map, "\e[1;8A", to_key("#up+W")); // + + + + + table_set(*key_map, "\e[1;2A", to_key("#up+$")); // + + + + + + table_set(*key_map, "\e[1;3A", to_key("#up+a")); // + + + + + + table_set(*key_map, "\e[1;4A", to_key("#up+A")); // + + + + + table_set(*key_map, "\e[1;5A", to_key("#up+c")); // + + + + + + table_set(*key_map, "\e[1;6A", to_key("#up+C")); // + + + + + table_set(*key_map, "\e[1;7A", to_key("#up+w")); // + + + + + + table_set(*key_map, "\e[1;8A", to_key("#up+W")); // + + + + + table_set(*key_map, "\e[1;9A", to_key("#up+s")); // + table_set(*key_map, "\e[1;10A", to_key("#up+S")); // + table_set(*key_map, "\e[1;11A", to_key("#up+x")); // + @@ -52,16 +53,16 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15A", to_key("#up+z")); // + table_set(*key_map, "\e[1;16A", to_key("#up+Z")); // + - // Down // g i k l x - table_set(*key_map, "\e[B", to_key("#down")); // + + + + + + // Down // g i k l w x + table_set(*key_map, "\e[B", to_key("#down")); // + + + + + + table_set(*key_map, "\e[1;1B", to_key("#down")); // - table_set(*key_map, "\e[1;2B", to_key("#down+$")); // + + + + - table_set(*key_map, "\e[1;3B", to_key("#down+a")); // + + + + - table_set(*key_map, "\e[1;4B", to_key("#down+A")); // + + + + - table_set(*key_map, "\e[1;5B", to_key("#down+c")); // + + + + - table_set(*key_map, "\e[1;6B", to_key("#down+C")); // + + + + - table_set(*key_map, "\e[1;7B", to_key("#down+w")); // + + + + - table_set(*key_map, "\e[1;8B", to_key("#down+W")); // + + + + + table_set(*key_map, "\e[1;2B", to_key("#down+$")); // + + + + + + table_set(*key_map, "\e[1;3B", to_key("#down+a")); // + + + + + + table_set(*key_map, "\e[1;4B", to_key("#down+A")); // + + + + + table_set(*key_map, "\e[1;5B", to_key("#down+c")); // + + + + + + table_set(*key_map, "\e[1;6B", to_key("#down+C")); // + + + + + table_set(*key_map, "\e[1;7B", to_key("#down+w")); // + + + + + + table_set(*key_map, "\e[1;8B", to_key("#down+W")); // + + + + + table_set(*key_map, "\e[1;9B", to_key("#down+s")); // + table_set(*key_map, "\e[1;10B", to_key("#down+S")); // + table_set(*key_map, "\e[1;11B", to_key("#down+x")); // + @@ -71,16 +72,16 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15B", to_key("#down+z")); // + table_set(*key_map, "\e[1;16B", to_key("#down+Z")); // + - // Right // g i k l x - table_set(*key_map, "\e[C", to_key("#right")); // + + + + + + // Right // g i k l w x + table_set(*key_map, "\e[C", to_key("#right")); // + + + + + + table_set(*key_map, "\e[1;1C", to_key("#right")); // - table_set(*key_map, "\e[1;2C", to_key("#right+$")); // + + + + - table_set(*key_map, "\e[1;3C", to_key("#right+a")); // + + + + - table_set(*key_map, "\e[1;4C", to_key("#right+A")); // + + + + - table_set(*key_map, "\e[1;5C", to_key("#right+c")); // + + + + - table_set(*key_map, "\e[1;6C", to_key("#right+C")); // + + + + - table_set(*key_map, "\e[1;7C", to_key("#right+w")); // + + + + - table_set(*key_map, "\e[1;8C", to_key("#right+W")); // + + + + + table_set(*key_map, "\e[1;2C", to_key("#right+$")); // + + + + + + table_set(*key_map, "\e[1;3C", to_key("#right+a")); // + + + + + + table_set(*key_map, "\e[1;4C", to_key("#right+A")); // + + + + + table_set(*key_map, "\e[1;5C", to_key("#right+c")); // + + + + + + table_set(*key_map, "\e[1;6C", to_key("#right+C")); // + + + + + + table_set(*key_map, "\e[1;7C", to_key("#right+w")); // + + + + + + table_set(*key_map, "\e[1;8C", to_key("#right+W")); // + + + + + table_set(*key_map, "\e[1;9C", to_key("#right+s")); // + table_set(*key_map, "\e[1;10C", to_key("#right+S")); // + table_set(*key_map, "\e[1;11C", to_key("#right+x")); // + @@ -90,16 +91,16 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15C", to_key("#right+z")); // + table_set(*key_map, "\e[1;16C", to_key("#right+Z")); // + - // Left // g i k l x - table_set(*key_map, "\e[D", to_key("#left")); // + + + + + + // Left // g i k l w x + table_set(*key_map, "\e[D", to_key("#left")); // + + + + + + table_set(*key_map, "\e[1;1D", to_key("#left")); // - table_set(*key_map, "\e[1;2D", to_key("#left+$")); // + + + + - table_set(*key_map, "\e[1;3D", to_key("#left+a")); // + + + + - table_set(*key_map, "\e[1;4D", to_key("#left+A")); // + + + + - table_set(*key_map, "\e[1;5D", to_key("#left+c")); // + + + + - table_set(*key_map, "\e[1;6D", to_key("#left+C")); // + + + + - table_set(*key_map, "\e[1;7D", to_key("#left+w")); // + + + + - table_set(*key_map, "\e[1;8D", to_key("#left+W")); // + + + + + table_set(*key_map, "\e[1;2D", to_key("#left+$")); // + + + + + + table_set(*key_map, "\e[1;3D", to_key("#left+a")); // + + + + + + table_set(*key_map, "\e[1;4D", to_key("#left+A")); // + + + + + + table_set(*key_map, "\e[1;5D", to_key("#left+c")); // + + + + + + table_set(*key_map, "\e[1;6D", to_key("#left+C")); // + + + + + + table_set(*key_map, "\e[1;7D", to_key("#left+w")); // + + + + + + table_set(*key_map, "\e[1;8D", to_key("#left+W")); // + + + + + table_set(*key_map, "\e[1;9D", to_key("#left+s")); // + table_set(*key_map, "\e[1;10D", to_key("#left+S")); // + table_set(*key_map, "\e[1;11D", to_key("#left+x")); // + @@ -109,17 +110,17 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15D", to_key("#left+z")); // + table_set(*key_map, "\e[1;16D", to_key("#left+Z")); // + - // Home // g i k l x + // Home // g i k l w x table_set(*key_map, "\e[1~", to_key("#home")); // + - table_set(*key_map, "\e[H", to_key("#home")); // + + + + + table_set(*key_map, "\e[H", to_key("#home")); // + + + + + table_set(*key_map, "\e[1;1H", to_key("#home")); // - table_set(*key_map, "\e[1;2H", to_key("#home+$")); // + + + + - table_set(*key_map, "\e[1;3H", to_key("#home+a")); // + + + + - table_set(*key_map, "\e[1;4H", to_key("#home+A")); // + + + + - table_set(*key_map, "\e[1;5H", to_key("#home+c")); // + + + + - table_set(*key_map, "\e[1;6H", to_key("#home+C")); // + + + + - table_set(*key_map, "\e[1;7H", to_key("#home+w")); // + + + + - table_set(*key_map, "\e[1;8H", to_key("#home+W")); // + + + + + table_set(*key_map, "\e[1;2H", to_key("#home+$")); // + + + + + + table_set(*key_map, "\e[1;3H", to_key("#home+a")); // + + + + + + table_set(*key_map, "\e[1;4H", to_key("#home+A")); // + + + + + + table_set(*key_map, "\e[1;5H", to_key("#home+c")); // + + + + + + table_set(*key_map, "\e[1;6H", to_key("#home+C")); // + + + + + table_set(*key_map, "\e[1;7H", to_key("#home+w")); // + + + + + + table_set(*key_map, "\e[1;8H", to_key("#home+W")); // + + + + + table_set(*key_map, "\e[1;9H", to_key("#home+s")); // + table_set(*key_map, "\e[1;10H", to_key("#home+S")); // + table_set(*key_map, "\e[1;11H", to_key("#home+x")); // + @@ -129,17 +130,17 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15H", to_key("#home+z")); // + table_set(*key_map, "\e[1;16H", to_key("#home+Z")); // + - // End // g i k l x + // End // g i k l w x table_set(*key_map, "\e[4~", to_key("#end")); // + - table_set(*key_map, "\e[F", to_key("#end")); // + + + + + table_set(*key_map, "\e[F", to_key("#end")); // + + + + + table_set(*key_map, "\e[1;1F", to_key("#end")); // - table_set(*key_map, "\e[1;2F", to_key("#end+$")); // + + + + - table_set(*key_map, "\e[1;3F", to_key("#end+a")); // + + + + - table_set(*key_map, "\e[1;4F", to_key("#end+A")); // + + + + - table_set(*key_map, "\e[1;5F", to_key("#end+c")); // + + + + - table_set(*key_map, "\e[1;6F", to_key("#end+C")); // + + + + - table_set(*key_map, "\e[1;7F", to_key("#end+w")); // + + + + - table_set(*key_map, "\e[1;8F", to_key("#end+W")); // + + + + + table_set(*key_map, "\e[1;2F", to_key("#end+$")); // + + + + + + table_set(*key_map, "\e[1;3F", to_key("#end+a")); // + + + + + + table_set(*key_map, "\e[1;4F", to_key("#end+A")); // + + + + + + table_set(*key_map, "\e[1;5F", to_key("#end+c")); // + + + + + table_set(*key_map, "\e[1;6F", to_key("#end+C")); // + + + + + table_set(*key_map, "\e[1;7F", to_key("#end+w")); // + + + + + + table_set(*key_map, "\e[1;8F", to_key("#end+W")); // + + + + + table_set(*key_map, "\e[1;9F", to_key("#end+s")); // + table_set(*key_map, "\e[1;10F", to_key("#end+S")); // + table_set(*key_map, "\e[1;11F", to_key("#end+x")); // + @@ -149,16 +150,16 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15F", to_key("#end+z")); // + table_set(*key_map, "\e[1;16F", to_key("#end+Z")); // + - // Insert // g i k l x - table_set(*key_map, "\e[2~", to_key("#ins")); // + + + + + + // Insert // g i k l w x + table_set(*key_map, "\e[2~", to_key("#ins")); // + + + + + + table_set(*key_map, "\e[2;1~", to_key("#ins")); // - table_set(*key_map, "\e[2;2~", to_key("#ins+$")); // + + + + - table_set(*key_map, "\e[2;3~", to_key("#ins+a")); // + + + + - table_set(*key_map, "\e[2;4~", to_key("#ins+A")); // + + + + - table_set(*key_map, "\e[2;5~", to_key("#ins+c")); // + + + + - table_set(*key_map, "\e[2;6~", to_key("#ins+C")); // + + + + - table_set(*key_map, "\e[2;7~", to_key("#ins+w")); // + + + + - table_set(*key_map, "\e[2;8~", to_key("#ins+W")); // + + + + + table_set(*key_map, "\e[2;2~", to_key("#ins+$")); // + + + + + + table_set(*key_map, "\e[2;3~", to_key("#ins+a")); // + + + + + + table_set(*key_map, "\e[2;4~", to_key("#ins+A")); // + + + + + + table_set(*key_map, "\e[2;5~", to_key("#ins+c")); // + + + + + + table_set(*key_map, "\e[2;6~", to_key("#ins+C")); // + + + + + + table_set(*key_map, "\e[2;7~", to_key("#ins+w")); // + + + + + + table_set(*key_map, "\e[2;8~", to_key("#ins+W")); // + + + + + table_set(*key_map, "\e[2;9~", to_key("#ins+s")); // + table_set(*key_map, "\e[2;10~", to_key("#ins+S")); // + table_set(*key_map, "\e[2;11~", to_key("#ins+x")); // + @@ -168,16 +169,16 @@ setup_key_map :: () { table_set(*key_map, "\e[2;15~", to_key("#ins+z")); // + table_set(*key_map, "\e[2;16~", to_key("#ins+Z")); // + - // Delete // g i k l x - table_set(*key_map, "\e[3~", to_key("#del")); // + + + + + + // Delete // g i k l w x + table_set(*key_map, "\e[3~", to_key("#del")); // + + + + + + table_set(*key_map, "\e[3;1~", to_key("#del")); // - table_set(*key_map, "\e[3;2~", to_key("#del+$")); // + + + + - table_set(*key_map, "\e[3;3~", to_key("#del+a")); // + + + + - table_set(*key_map, "\e[3;4~", to_key("#del+A")); // + + + + - table_set(*key_map, "\e[3;5~", to_key("#del+c")); // + + + + - table_set(*key_map, "\e[3;6~", to_key("#del+C")); // + + + + - table_set(*key_map, "\e[3;7~", to_key("#del+w")); // + + + + - table_set(*key_map, "\e[3;8~", to_key("#del+W")); // + + + + + table_set(*key_map, "\e[3;2~", to_key("#del+$")); // + + + + + + table_set(*key_map, "\e[3;3~", to_key("#del+a")); // + + + + + + table_set(*key_map, "\e[3;4~", to_key("#del+A")); // + + + + + + table_set(*key_map, "\e[3;5~", to_key("#del+c")); // + + + + + + table_set(*key_map, "\e[3;6~", to_key("#del+C")); // + + + + + + table_set(*key_map, "\e[3;7~", to_key("#del+w")); // + + + + + + table_set(*key_map, "\e[3;8~", to_key("#del+W")); // + + + + + table_set(*key_map, "\e[3;9~", to_key("#del+s")); // + table_set(*key_map, "\e[3;10~", to_key("#del+S")); // + table_set(*key_map, "\e[3;11~", to_key("#del+x")); // + @@ -187,16 +188,16 @@ setup_key_map :: () { table_set(*key_map, "\e[3;15~", to_key("#del+z")); // + table_set(*key_map, "\e[3;16~", to_key("#del+Z")); // + - // Page Up // g i k l x - table_set(*key_map, "\e[5~", to_key("#pup")); // + + + + + + // Page Up // g i k l w x + table_set(*key_map, "\e[5~", to_key("#pup")); // + + + + + + table_set(*key_map, "\e[5;1~", to_key("#pup")); // - table_set(*key_map, "\e[5;2~", to_key("#pup+$")); // + + + + - table_set(*key_map, "\e[5;3~", to_key("#pup+a")); // + + + + - table_set(*key_map, "\e[5;4~", to_key("#pup+A")); // + + + + - table_set(*key_map, "\e[5;5~", to_key("#pup+c")); // + + + + - table_set(*key_map, "\e[5;6~", to_key("#pup+C")); // + + + + - table_set(*key_map, "\e[5;7~", to_key("#pup+w")); // + + + + - table_set(*key_map, "\e[5;8~", to_key("#pup+W")); // + + + + + table_set(*key_map, "\e[5;2~", to_key("#pup+$")); // + + + + + + table_set(*key_map, "\e[5;3~", to_key("#pup+a")); // + + + + + + table_set(*key_map, "\e[5;4~", to_key("#pup+A")); // + + + + + + table_set(*key_map, "\e[5;5~", to_key("#pup+c")); // + + + + + + table_set(*key_map, "\e[5;6~", to_key("#pup+C")); // + + + + + table_set(*key_map, "\e[5;7~", to_key("#pup+w")); // + + + + + + table_set(*key_map, "\e[5;8~", to_key("#pup+W")); // + + + + + table_set(*key_map, "\e[5;9~", to_key("#pup+s")); // + table_set(*key_map, "\e[5;10~", to_key("#pup+S")); // + table_set(*key_map, "\e[5;11~", to_key("#pup+x")); // + @@ -206,16 +207,16 @@ setup_key_map :: () { table_set(*key_map, "\e[5;15~", to_key("#pup+z")); // + table_set(*key_map, "\e[5;16~", to_key("#pup+Z")); // + - // Page Down // g i k l x - table_set(*key_map, "\e[6~", to_key("#pdown")); // + + + + + + // Page Down // g i k l w x + table_set(*key_map, "\e[6~", to_key("#pdown")); // + + + + + + table_set(*key_map, "\e[6;1~", to_key("#pdown")); // - table_set(*key_map, "\e[6;2~", to_key("#pdown+$")); // + + + + - table_set(*key_map, "\e[6;3~", to_key("#pdown+a")); // + + + + - table_set(*key_map, "\e[6;4~", to_key("#pdown+A")); // + + + + - table_set(*key_map, "\e[6;5~", to_key("#pdown+c")); // + + + + - table_set(*key_map, "\e[6;6~", to_key("#pdown+C")); // + + + + - table_set(*key_map, "\e[6;7~", to_key("#pdown+w")); // + + + + - table_set(*key_map, "\e[6;8~", to_key("#pdown+W")); // + + + + + table_set(*key_map, "\e[6;2~", to_key("#pdown+$")); // + + + + + + table_set(*key_map, "\e[6;3~", to_key("#pdown+a")); // + + + + + + table_set(*key_map, "\e[6;4~", to_key("#pdown+A")); // + + + + + + table_set(*key_map, "\e[6;5~", to_key("#pdown+c")); // + + + + + + table_set(*key_map, "\e[6;6~", to_key("#pdown+C")); // + + + + + table_set(*key_map, "\e[6;7~", to_key("#pdown+w")); // + + + + + + table_set(*key_map, "\e[6;8~", to_key("#pdown+W")); // + + + + + table_set(*key_map, "\e[6;9~", to_key("#pdown+s")); // + table_set(*key_map, "\e[6;10~", to_key("#pdown+S")); // + table_set(*key_map, "\e[6;11~", to_key("#pdown+x")); // + @@ -225,10 +226,10 @@ setup_key_map :: () { table_set(*key_map, "\e[6;15~", to_key("#pdown+z")); // + table_set(*key_map, "\e[6;16~", to_key("#pdown+Z")); // + - // F1 // g i k l x + // F1 // g i k l w x table_set(*key_map, "\e[[A", to_key("#f1")); // + table_set(*key_map, "\e[25~", to_key("#f1+$")); // + - table_set(*key_map, "\eOP", to_key("#f1")); // + + + + + table_set(*key_map, "\eOP", to_key("#f1")); // + + + + + table_set(*key_map, "\eO1P", to_key("#f1+s")); // + table_set(*key_map, "\eO2P", to_key("#f1+$")); // + table_set(*key_map, "\eO3P", to_key("#f1+a")); // + @@ -239,13 +240,13 @@ setup_key_map :: () { table_set(*key_map, "\eO8P", to_key("#f1+W")); // + table_set(*key_map, "\e[1P", to_key("#f1")); // table_set(*key_map, "\e[1;1P", to_key("#f1")); // - table_set(*key_map, "\e[1;2P", to_key("#f1+$")); // + + + - table_set(*key_map, "\e[1;3P", to_key("#f1+a")); // + + + - table_set(*key_map, "\e[1;4P", to_key("#f1+A")); // + + + - table_set(*key_map, "\e[1;5P", to_key("#f1+c")); // + + + - table_set(*key_map, "\e[1;6P", to_key("#f1+C")); // + + + - table_set(*key_map, "\e[1;7P", to_key("#f1+w")); // + + + - table_set(*key_map, "\e[1;8P", to_key("#f1+W")); // + + + + table_set(*key_map, "\e[1;2P", to_key("#f1+$")); // + + + + + table_set(*key_map, "\e[1;3P", to_key("#f1+a")); // + + + + + table_set(*key_map, "\e[1;4P", to_key("#f1+A")); // + + + + + table_set(*key_map, "\e[1;5P", to_key("#f1+c")); // + + + + + table_set(*key_map, "\e[1;6P", to_key("#f1+C")); // + + + + + table_set(*key_map, "\e[1;7P", to_key("#f1+w")); // + + + + + table_set(*key_map, "\e[1;8P", to_key("#f1+W")); // + + + + table_set(*key_map, "\e[1;9P", to_key("#f1+s")); // + table_set(*key_map, "\e[1;10P", to_key("#f1+S")); // + table_set(*key_map, "\e[1;11P", to_key("#f1+x")); // + @@ -255,10 +256,10 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15P", to_key("#f1+z")); // + table_set(*key_map, "\e[1;16P", to_key("#f1+Z")); // + - // F2 // g i k l x + // F2 // g i k l w x table_set(*key_map, "\e[[B", to_key("#f2")); // + table_set(*key_map, "\e[26~", to_key("#f2+$")); // + - table_set(*key_map, "\eOQ", to_key("#f2")); // + + + + + table_set(*key_map, "\eOQ", to_key("#f2")); // + + + + + table_set(*key_map, "\eO1Q", to_key("#f2+s")); // + table_set(*key_map, "\eO2Q", to_key("#f2+$")); // + table_set(*key_map, "\eO3Q", to_key("#f2+a")); // + @@ -269,13 +270,13 @@ setup_key_map :: () { table_set(*key_map, "\eO8Q", to_key("#f2+W")); // + table_set(*key_map, "\e[1Q", to_key("#f2")); // table_set(*key_map, "\e[1;1Q", to_key("#f2")); // - table_set(*key_map, "\e[1;2Q", to_key("#f2+$")); // + + + - table_set(*key_map, "\e[1;3Q", to_key("#f2+a")); // + + + - table_set(*key_map, "\e[1;4Q", to_key("#f2+A")); // + + + - table_set(*key_map, "\e[1;5Q", to_key("#f2+c")); // + + + - table_set(*key_map, "\e[1;6Q", to_key("#f2+C")); // + + + - table_set(*key_map, "\e[1;7Q", to_key("#f2+w")); // + + + - table_set(*key_map, "\e[1;8Q", to_key("#f2+W")); // + + + + table_set(*key_map, "\e[1;2Q", to_key("#f2+$")); // + + + + + table_set(*key_map, "\e[1;3Q", to_key("#f2+a")); // + + + + + table_set(*key_map, "\e[1;4Q", to_key("#f2+A")); // + + + + + table_set(*key_map, "\e[1;5Q", to_key("#f2+c")); // + + + + + table_set(*key_map, "\e[1;6Q", to_key("#f2+C")); // + + + + + table_set(*key_map, "\e[1;7Q", to_key("#f2+w")); // + + + + + table_set(*key_map, "\e[1;8Q", to_key("#f2+W")); // + + + + table_set(*key_map, "\e[1;9Q", to_key("#f2+s")); // + table_set(*key_map, "\e[1;10Q", to_key("#f2+S")); // + table_set(*key_map, "\e[1;11Q", to_key("#f2+x")); // + @@ -285,10 +286,10 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15Q", to_key("#f2+z")); // + table_set(*key_map, "\e[1;16Q", to_key("#f2+Z")); // + - // F3 // g i k l x + // F3 // g i k l w x table_set(*key_map, "\e[[C", to_key("#f3")); // + table_set(*key_map, "\e[28~", to_key("#f3+$")); // + - table_set(*key_map, "\eOR", to_key("#f3")); // + + + + + table_set(*key_map, "\eOR", to_key("#f3")); // + + + + + table_set(*key_map, "\eO1R", to_key("#f3+s")); // + table_set(*key_map, "\eO2R", to_key("#f3+$")); // + table_set(*key_map, "\eO3R", to_key("#f3+a")); // + @@ -299,13 +300,13 @@ setup_key_map :: () { table_set(*key_map, "\eO8R", to_key("#f3+W")); // + table_set(*key_map, "\e[1R", to_key("#f3")); // table_set(*key_map, "\e[1;1R", to_key("#f3")); // - table_set(*key_map, "\e[1;2R", to_key("#f3+$")); // + + + - table_set(*key_map, "\e[1;3R", to_key("#f3+a")); // + + + - table_set(*key_map, "\e[1;4R", to_key("#f3+A")); // + + + - table_set(*key_map, "\e[1;5R", to_key("#f3+c")); // + + + - table_set(*key_map, "\e[1;6R", to_key("#f3+C")); // + + + - table_set(*key_map, "\e[1;7R", to_key("#f3+w")); // + + + - table_set(*key_map, "\e[1;8R", to_key("#f3+W")); // + + + + table_set(*key_map, "\e[1;2R", to_key("#f3+$")); // + + + + + table_set(*key_map, "\e[1;3R", to_key("#f3+a")); // + + + + + table_set(*key_map, "\e[1;4R", to_key("#f3+A")); // + + + + + table_set(*key_map, "\e[1;5R", to_key("#f3+c")); // + + + + + table_set(*key_map, "\e[1;6R", to_key("#f3+C")); // + + + + + table_set(*key_map, "\e[1;7R", to_key("#f3+w")); // + + + + + table_set(*key_map, "\e[1;8R", to_key("#f3+W")); // + + + + table_set(*key_map, "\e[1;9R", to_key("#f3+s")); // + table_set(*key_map, "\e[1;10R", to_key("#f3+S")); // + table_set(*key_map, "\e[1;11R", to_key("#f3+x")); // + @@ -315,10 +316,10 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15R", to_key("#f3+z")); // + table_set(*key_map, "\e[1;16R", to_key("#f3+Z")); // + - // F4 // g i k l x + // F4 // g i k l w x table_set(*key_map, "\e[[D", to_key("#f4")); // + table_set(*key_map, "\e[29~", to_key("#f4+$")); // + - table_set(*key_map, "\eOS", to_key("#f4")); // + + + + + table_set(*key_map, "\eOS", to_key("#f4")); // + + + + + table_set(*key_map, "\eO1S", to_key("#f4+s")); // + table_set(*key_map, "\eO2S", to_key("#f4+$")); // + table_set(*key_map, "\eO3S", to_key("#f4+a")); // + @@ -329,13 +330,13 @@ setup_key_map :: () { table_set(*key_map, "\eO8S", to_key("#f4+W")); // + table_set(*key_map, "\e[1S", to_key("#f4")); // table_set(*key_map, "\e[1;1S", to_key("#f4")); // - table_set(*key_map, "\e[1;2S", to_key("#f4+$")); // + + + - table_set(*key_map, "\e[1;3S", to_key("#f4+a")); // + + + - table_set(*key_map, "\e[1;4S", to_key("#f4+A")); // + + + - table_set(*key_map, "\e[1;5S", to_key("#f4+c")); // + + + - table_set(*key_map, "\e[1;6S", to_key("#f4+C")); // + + + - table_set(*key_map, "\e[1;7S", to_key("#f4+w")); // + + + - table_set(*key_map, "\e[1;8S", to_key("#f4+W")); // + + + + table_set(*key_map, "\e[1;2S", to_key("#f4+$")); // + + + + + table_set(*key_map, "\e[1;3S", to_key("#f4+a")); // + + + + + table_set(*key_map, "\e[1;4S", to_key("#f4+A")); // + + + + + table_set(*key_map, "\e[1;5S", to_key("#f4+c")); // + + + + + table_set(*key_map, "\e[1;6S", to_key("#f4+C")); // + + + + + table_set(*key_map, "\e[1;7S", to_key("#f4+w")); // + + + + + table_set(*key_map, "\e[1;8S", to_key("#f4+W")); // + + + + table_set(*key_map, "\e[1;9S", to_key("#f4+s")); // + table_set(*key_map, "\e[1;10S", to_key("#f4+S")); // + table_set(*key_map, "\e[1;11S", to_key("#f4+x")); // + @@ -345,18 +346,18 @@ setup_key_map :: () { table_set(*key_map, "\e[1;15S", to_key("#f4+z")); // + table_set(*key_map, "\e[1;16S", to_key("#f4+Z")); // + - // F5 // g i k l x + // F5 // g i k l w x table_set(*key_map, "\e[[E", to_key("#f5")); // + table_set(*key_map, "\e[31~", to_key("#f5+$")); // + - table_set(*key_map, "\e[15~", to_key("#f5")); // + + + + + table_set(*key_map, "\e[15~", to_key("#f5")); // + + + + + table_set(*key_map, "\e[15;1~", to_key("#f5")); // - table_set(*key_map, "\e[15;2~", to_key("#f5+$")); // + + + + - table_set(*key_map, "\e[15;3~", to_key("#f5+a")); // + + + + - table_set(*key_map, "\e[15;4~", to_key("#f5+A")); // + + + + - table_set(*key_map, "\e[15;5~", to_key("#f5+c")); // + + + + - table_set(*key_map, "\e[15;6~", to_key("#f5+C")); // + + + + - table_set(*key_map, "\e[15;7~", to_key("#f5+w")); // + + + + - table_set(*key_map, "\e[15;8~", to_key("#f5+W")); // + + + + + table_set(*key_map, "\e[15;2~", to_key("#f5+$")); // + + + + + + table_set(*key_map, "\e[15;3~", to_key("#f5+a")); // + + + + + + table_set(*key_map, "\e[15;4~", to_key("#f5+A")); // + + + + + + table_set(*key_map, "\e[15;5~", to_key("#f5+c")); // + + + + + + table_set(*key_map, "\e[15;6~", to_key("#f5+C")); // + + + + + + table_set(*key_map, "\e[15;7~", to_key("#f5+w")); // + + + + + + table_set(*key_map, "\e[15;8~", to_key("#f5+W")); // + + + + + table_set(*key_map, "\e[15;9~", to_key("#f5+s")); // + table_set(*key_map, "\e[15;10~",to_key("#f5+S")); // + table_set(*key_map, "\e[15;11~",to_key("#f5+x")); // + @@ -366,17 +367,17 @@ setup_key_map :: () { table_set(*key_map, "\e[15;15~",to_key("#f5+z")); // + table_set(*key_map, "\e[15;16~",to_key("#f5+Z")); // + - // F6 // g i k l x + // F6 // g i k l w x table_set(*key_map, "\e[32~", to_key("#f6+$")); // + - table_set(*key_map, "\e[17~", to_key("#f6")); // + + + + + + table_set(*key_map, "\e[17~", to_key("#f6")); // + + + + + + table_set(*key_map, "\e[17;1~", to_key("#f6")); // - table_set(*key_map, "\e[17;2~", to_key("#f6+$")); // + + + + - table_set(*key_map, "\e[17;3~", to_key("#f6+a")); // + + + + - table_set(*key_map, "\e[17;4~", to_key("#f6+A")); // + + + + - table_set(*key_map, "\e[17;5~", to_key("#f6+c")); // + + + + - table_set(*key_map, "\e[17;6~", to_key("#f6+C")); // + + + + - table_set(*key_map, "\e[17;7~", to_key("#f6+w")); // + + + + - table_set(*key_map, "\e[17;8~", to_key("#f6+W")); // + + + + + table_set(*key_map, "\e[17;2~", to_key("#f6+$")); // + + + + + + table_set(*key_map, "\e[17;3~", to_key("#f6+a")); // + + + + + + table_set(*key_map, "\e[17;4~", to_key("#f6+A")); // + + + + + + table_set(*key_map, "\e[17;5~", to_key("#f6+c")); // + + + + + + table_set(*key_map, "\e[17;6~", to_key("#f6+C")); // + + + + + + table_set(*key_map, "\e[17;7~", to_key("#f6+w")); // + + + + + + table_set(*key_map, "\e[17;8~", to_key("#f6+W")); // + + + + + table_set(*key_map, "\e[17;9~", to_key("#f6+s")); // + table_set(*key_map, "\e[17;10~",to_key("#f6+S")); // + table_set(*key_map, "\e[17;11~",to_key("#f6+x")); // + @@ -386,17 +387,17 @@ setup_key_map :: () { table_set(*key_map, "\e[17;15~",to_key("#f6+z")); // + table_set(*key_map, "\e[17;16~",to_key("#f6+Z")); // + - // F7 // g i k l x + // F7 // g i k l w x table_set(*key_map, "\e[33~", to_key("#f7+$")); // + - table_set(*key_map, "\e[18~", to_key("#f7")); // + + + + + + table_set(*key_map, "\e[18~", to_key("#f7")); // + + + + + + table_set(*key_map, "\e[18;1~", to_key("#f7")); // - table_set(*key_map, "\e[18;2~", to_key("#f7+$")); // + + + + - table_set(*key_map, "\e[18;3~", to_key("#f7+a")); // + + + + - table_set(*key_map, "\e[18;4~", to_key("#f7+A")); // + + + + - table_set(*key_map, "\e[18;5~", to_key("#f7+c")); // + + + + - table_set(*key_map, "\e[18;6~", to_key("#f7+C")); // + + + + - table_set(*key_map, "\e[18;7~", to_key("#f7+w")); // + + + + - table_set(*key_map, "\e[18;8~", to_key("#f7+W")); // + + + + + table_set(*key_map, "\e[18;2~", to_key("#f7+$")); // + + + + + + table_set(*key_map, "\e[18;3~", to_key("#f7+a")); // + + + + + + table_set(*key_map, "\e[18;4~", to_key("#f7+A")); // + + + + + + table_set(*key_map, "\e[18;5~", to_key("#f7+c")); // + + + + + + table_set(*key_map, "\e[18;6~", to_key("#f7+C")); // + + + + + + table_set(*key_map, "\e[18;7~", to_key("#f7+w")); // + + + + + + table_set(*key_map, "\e[18;8~", to_key("#f7+W")); // + + + + + table_set(*key_map, "\e[18;9~", to_key("#f7+s")); // + table_set(*key_map, "\e[18;10~",to_key("#f7+S")); // + table_set(*key_map, "\e[18;11~",to_key("#f7+x")); // + @@ -406,17 +407,17 @@ setup_key_map :: () { table_set(*key_map, "\e[18;15~",to_key("#f7+z")); // + table_set(*key_map, "\e[18;16~",to_key("#f7+Z")); // + - // F8 // g i k l x + // F8 // g i k l w x table_set(*key_map, "\e[34~", to_key("#f8+$")); // + - table_set(*key_map, "\e[19~", to_key("#f8")); // + + + + + + table_set(*key_map, "\e[19~", to_key("#f8")); // + + + + + + table_set(*key_map, "\e[19;1~", to_key("#f8")); // - table_set(*key_map, "\e[19;2~", to_key("#f8+$")); // + + + + - table_set(*key_map, "\e[19;3~", to_key("#f8+a")); // + + + + - table_set(*key_map, "\e[19;4~", to_key("#f8+A")); // + + + + - table_set(*key_map, "\e[19;5~", to_key("#f8+c")); // + + + + - table_set(*key_map, "\e[19;6~", to_key("#f8+C")); // + + + + - table_set(*key_map, "\e[19;7~", to_key("#f8+w")); // + + + + - table_set(*key_map, "\e[19;8~", to_key("#f8+W")); // + + + + + table_set(*key_map, "\e[19;2~", to_key("#f8+$")); // + + + + + + table_set(*key_map, "\e[19;3~", to_key("#f8+a")); // + + + + + + table_set(*key_map, "\e[19;4~", to_key("#f8+A")); // + + + + + + table_set(*key_map, "\e[19;5~", to_key("#f8+c")); // + + + + + + table_set(*key_map, "\e[19;6~", to_key("#f8+C")); // + + + + + + table_set(*key_map, "\e[19;7~", to_key("#f8+w")); // + + + + + + table_set(*key_map, "\e[19;8~", to_key("#f8+W")); // + + + + + table_set(*key_map, "\e[19;9~", to_key("#f8+s")); // + table_set(*key_map, "\e[19;10~",to_key("#f8+S")); // + table_set(*key_map, "\e[19;11~",to_key("#f8+x")); // + @@ -426,16 +427,16 @@ setup_key_map :: () { table_set(*key_map, "\e[19;15~",to_key("#f8+z")); // + table_set(*key_map, "\e[19;16~",to_key("#f8+Z")); // + - // F9 // g i k l x - table_set(*key_map, "\e[20~", to_key("#f9")); // + + + + + + // F9 // g i k l w x + table_set(*key_map, "\e[20~", to_key("#f9")); // + + + + + + table_set(*key_map, "\e[20;1~", to_key("#f9")); // - table_set(*key_map, "\e[20;2~", to_key("#f9+$")); // + + + + - table_set(*key_map, "\e[20;3~", to_key("#f9+a")); // + + + + - table_set(*key_map, "\e[20;4~", to_key("#f9+A")); // + + + + - table_set(*key_map, "\e[20;5~", to_key("#f9+c")); // + + + + - table_set(*key_map, "\e[20;6~", to_key("#f9+C")); // + + + + - table_set(*key_map, "\e[20;7~", to_key("#f9+w")); // + + + + - table_set(*key_map, "\e[20;8~", to_key("#f9+W")); // + + + + + table_set(*key_map, "\e[20;2~", to_key("#f9+$")); // + + + + + + table_set(*key_map, "\e[20;3~", to_key("#f9+a")); // + + + + + + table_set(*key_map, "\e[20;4~", to_key("#f9+A")); // + + + + + + table_set(*key_map, "\e[20;5~", to_key("#f9+c")); // + + + + + + table_set(*key_map, "\e[20;6~", to_key("#f9+C")); // + + + + + + table_set(*key_map, "\e[20;7~", to_key("#f9+w")); // + + + + + + table_set(*key_map, "\e[20;8~", to_key("#f9+W")); // + + + + + table_set(*key_map, "\e[20;9~", to_key("#f9+s")); // + table_set(*key_map, "\e[20;10~",to_key("#f9+S")); // + table_set(*key_map, "\e[20;11~",to_key("#f9+x")); // + @@ -445,16 +446,16 @@ setup_key_map :: () { table_set(*key_map, "\e[20;15~",to_key("#f9+z")); // + table_set(*key_map, "\e[20;16~",to_key("#f9+Z")); // + - // F10 // g i k l x - table_set(*key_map, "\e[21~", to_key("#f10")); // + + + + + + // F10 // g i k l w x + table_set(*key_map, "\e[21~", to_key("#f10")); // + + + + + + table_set(*key_map, "\e[21;1~", to_key("#f10")); // - table_set(*key_map, "\e[21;2~", to_key("#f10+$")); // + + + + - table_set(*key_map, "\e[21;3~", to_key("#f10+a")); // + + + + - table_set(*key_map, "\e[21;4~", to_key("#f10+A")); // + + + + - table_set(*key_map, "\e[21;5~", to_key("#f10+c")); // + + + + - table_set(*key_map, "\e[21;6~", to_key("#f10+C")); // + + + + - table_set(*key_map, "\e[21;7~", to_key("#f10+w")); // + + + + - table_set(*key_map, "\e[21;8~", to_key("#f10+W")); // + + + + + table_set(*key_map, "\e[21;2~", to_key("#f10+$")); // + + + + + + table_set(*key_map, "\e[21;3~", to_key("#f10+a")); // + + + + + + table_set(*key_map, "\e[21;4~", to_key("#f10+A")); // + + + + + + table_set(*key_map, "\e[21;5~", to_key("#f10+c")); // + + + + + + table_set(*key_map, "\e[21;6~", to_key("#f10+C")); // + + + + + + table_set(*key_map, "\e[21;7~", to_key("#f10+w")); // + + + + + + table_set(*key_map, "\e[21;8~", to_key("#f10+W")); // + + + + + table_set(*key_map, "\e[21;9~", to_key("#f10+s")); // + table_set(*key_map, "\e[21;10~",to_key("#f10+S")); // + table_set(*key_map, "\e[21;11~",to_key("#f10+x")); // + @@ -464,16 +465,16 @@ setup_key_map :: () { table_set(*key_map, "\e[21;15~",to_key("#f10+z")); // + table_set(*key_map, "\e[21;16~",to_key("#f10+Z")); // + - // F11 // g i k l x - table_set(*key_map, "\e[23~", to_key("#f11")); // + + + + + + // F11 // g i k l w x + table_set(*key_map, "\e[23~", to_key("#f11")); // + + + + + + table_set(*key_map, "\e[23;1~", to_key("#f11")); // - table_set(*key_map, "\e[23;2~", to_key("#f11+$")); // + + + + - table_set(*key_map, "\e[23;3~", to_key("#f11+a")); // + + + + - table_set(*key_map, "\e[23;4~", to_key("#f11+A")); // + + + + - table_set(*key_map, "\e[23;5~", to_key("#f11+c")); // + + + + - table_set(*key_map, "\e[23;6~", to_key("#f11+C")); // + + + + - table_set(*key_map, "\e[23;7~", to_key("#f11+w")); // + + + + - table_set(*key_map, "\e[23;8~", to_key("#f11+W")); // + + + + + table_set(*key_map, "\e[23;2~", to_key("#f11+$")); // + + + + + + table_set(*key_map, "\e[23;3~", to_key("#f11+a")); // + + + + + + table_set(*key_map, "\e[23;4~", to_key("#f11+A")); // + + + + + + table_set(*key_map, "\e[23;5~", to_key("#f11+c")); // + + + + + + table_set(*key_map, "\e[23;6~", to_key("#f11+C")); // + + + + + + table_set(*key_map, "\e[23;7~", to_key("#f11+w")); // + + + + + + table_set(*key_map, "\e[23;8~", to_key("#f11+W")); // + + + + + table_set(*key_map, "\e[23;9~", to_key("#f11+s")); // + table_set(*key_map, "\e[23;10~",to_key("#f11+S")); // + table_set(*key_map, "\e[23;11~",to_key("#f11+x")); // + @@ -483,16 +484,16 @@ setup_key_map :: () { table_set(*key_map, "\e[23;15~",to_key("#f11+z")); // + table_set(*key_map, "\e[23;16~",to_key("#f11+Z")); // + - // F12 // g i k l x - table_set(*key_map, "\e[24~", to_key("#f12")); // + + + + + + // F12 // g i k l w x + table_set(*key_map, "\e[24~", to_key("#f12")); // + + + + + + table_set(*key_map, "\e[24;1~", to_key("#f12")); // - table_set(*key_map, "\e[24;2~", to_key("#f12+$")); // + + + + - table_set(*key_map, "\e[24;3~", to_key("#f12+a")); // + + + + - table_set(*key_map, "\e[24;4~", to_key("#f12+A")); // + + + + - table_set(*key_map, "\e[24;5~", to_key("#f12+c")); // + + + + - table_set(*key_map, "\e[24;6~", to_key("#f12+C")); // + + + + - table_set(*key_map, "\e[24;7~", to_key("#f12+w")); // + + + + - table_set(*key_map, "\e[24;8~", to_key("#f12+W")); // + + + + + table_set(*key_map, "\e[24;2~", to_key("#f12+$")); // + + + + + + table_set(*key_map, "\e[24;3~", to_key("#f12+a")); // + + + + + + table_set(*key_map, "\e[24;4~", to_key("#f12+A")); // + + + + + + table_set(*key_map, "\e[24;5~", to_key("#f12+c")); // + + + + + + table_set(*key_map, "\e[24;6~", to_key("#f12+C")); // + + + + + + table_set(*key_map, "\e[24;7~", to_key("#f12+w")); // + + + + + + table_set(*key_map, "\e[24;8~", to_key("#f12+W")); // + + + + + table_set(*key_map, "\e[24;9~", to_key("#f12+s")); // + table_set(*key_map, "\e[24;10~",to_key("#f12+S")); // + table_set(*key_map, "\e[24;11~",to_key("#f12+x")); // + diff --git a/modules/TUI/tests.jai b/modules/TUI/tests.jai index fe213cb..a740e6b 100644 --- a/modules/TUI/tests.jai +++ b/modules/TUI/tests.jai @@ -31,21 +31,6 @@ main :: () { assert_result(x == X && y == Y, "Failed set/get cursor position.\n"); } - if 1 { - print("TEST : module logger\n", to_standard_error = true); - log("- log: before module start."); - assert(TUI.setup_terminal(), "Failed to setup TUI."); - TUI.set_cursor_position(3, 3); - print("wait"); - sleep_milliseconds(500); - log("- log: while module is active."); - sleep_milliseconds(500); - print(" a bit"); - sleep_milliseconds(1000); - assert(TUI.reset_terminal(), "Failed to reset TUI."); - log("- log: after module stop."); - } - if 1 { print("TEST : test key input\n", to_standard_error = true); auto_release_temp(); @@ -121,7 +106,7 @@ main :: () { print("TEST : print keys\n", to_standard_error = true); auto_release_temp(); assert(TUI.setup_terminal(), "Failed to setup TUI."); - key: TUI.Key = #char "d"; + key: TUI.Key = TUI.Keys.None; last_none_char := "X"; width, height := TUI.get_terminal_size(); @@ -135,7 +120,7 @@ main :: () { case TUI.Keys.None; { TUI.set_cursor_position(2, 2); last_none_char = ifx last_none_char == "X" then "+" else "X"; - write_strings(last_none_char, " (press q to exit)"); + write_strings(last_none_char, " (press: q to exit, c to clear, and any other key to print it's value)"); } case TUI.Keys.Resize; #through; diff --git a/modules/UTF8.jai b/modules/UTF8.jai deleted file mode 100644 index 72d3d75..0000000 --- a/modules/UTF8.jai +++ /dev/null @@ -1,128 +0,0 @@ -// Some procedures to help working with UTF8 strings. -// https://en.wikipedia.org/wiki/UTF-8 - -// Returns true if argument is a continuation byte. -is_continuation_byte :: inline (byte: u8) -> bool { - // BBBB BBBB & 1100 0000 == 10XX XXXX -> is continuation byte - return (byte & 0xC0) == 0x80; -} - -// Given a leading_byte, returns the number of bytes on the character. -count_character_bytes :: inline (leading_byte: u8) -> int { - // BBBB BBBB & 1110 0000 == 110X XXXX -> 1 initial + 1 continuation byte - if (leading_byte & 0xE0) == 0xC0 return 1+1; - - // BBBB BBBB & 1111 0000 == 1110 XXXX -> 1 initial + 2 continuation byte - if (leading_byte & 0xF0) == 0xE0 return 1+2; - - // BBBB BBBB & 1111 1000 == 1111 0XXX -> 1 initial + 3 continuation byte - if (leading_byte & 0xF8) == 0xF0 return 1+3; - - return 1; -} - -// Returns the string (using same str.data) truncated to the provided length. -truncate :: (str: string, length: int) -> string { - - if str.data == null then return ""; - - if str.count < length then return .{str.count, str.data}; - - data := str.data; - count := str.count; - - // Find index of first continuation byte. - idx := length; - while (idx > 0 && is_continuation_byte(data[idx - 1])) { - idx -= 1; - } - continuation_bytes := length - idx; - - // If string starts with continuation bytes, it's an invalid UTF8 string. - if (idx == 0 && continuation_bytes > 0) { - length = 0; - } - // If length truncates some continuation bytes, remove incomplete UTF8 character. - else if (idx > 0 // string is not empty - // continuation bytes are not complete - && !(continuation_bytes == 0 && (data[idx - 1] & 0x80) == 0x00) - && !(continuation_bytes == 1 && (data[idx - 1] & 0xE0) == 0xC0) - && !(continuation_bytes == 2 && (data[idx - 1] & 0xF0) == 0xE0) - && !(continuation_bytes == 3 && (data[idx - 1] & 0xF8) == 0xF0) - ) { - length -= (continuation_bytes + 1); // Remove start byte, hence '+ 1'. - } - - return .{length, str.data}; -} - -// Returns true when the string is empty or consists of space characters. -is_empty :: (str: string) -> bool { - for 0..str.count-1 { - if str[it] == { - case #char "\0"; #through; - case #char "\t"; #through; // horizontal tab - case #char "\n"; #through; // line feed - case #char "\x0B"; #through; // vertical tabulation - case #char "\x0C"; #through; // form feed - case #char "\r"; #through; // carriage return - case #char " "; - continue; - case; - return false; - } - } - return true; -} - -// Counts the number of characters. -count_characters :: (str: string, $is_null_terminated := false) -> int { - characters := 0; - idx := 0; - - #if is_null_terminated { - while idx < str.count && str[idx] != 0 { - idx += count_character_bytes(str[idx]); - characters += 1; - } - } - else { - while idx < str.count { - idx += count_character_bytes(str[idx]); - characters += 1; - } - } - - return characters; -} - -// Deletes character by it's index, and moves tail data to take its place. -delete_character :: (str: *string, character_idx: int) -> success := true { - buffer_idx := get_byte_index(str.*, character_idx); - - if buffer_idx < 0 return false; - - bytes_to_delete := count_character_bytes(str.data[buffer_idx]); - - for buffer_idx..str.count-1-bytes_to_delete { - str.data[it] = str.data[it+bytes_to_delete]; - } - for str.count-bytes_to_delete..str.count-1 { - str.data[it] = 0; - } - - str.count -= bytes_to_delete; - return; -} - -// Searches for the given character index and returns its byte index on the string. -get_byte_index :: (str: string, character_index: int) -> buffer_index: int, success := true { - buff_idx := 0; - char_idx := 0; - while buff_idx < str.count { - if char_idx == character_index return buff_idx; - buff_idx += count_character_bytes(str[buff_idx]); - char_idx += 1; - } - return -1, false; -} diff --git a/modules/UTF8/module.jai b/modules/UTF8/module.jai new file mode 100644 index 0000000..72d3d75 --- /dev/null +++ b/modules/UTF8/module.jai @@ -0,0 +1,128 @@ +// Some procedures to help working with UTF8 strings. +// https://en.wikipedia.org/wiki/UTF-8 + +// Returns true if argument is a continuation byte. +is_continuation_byte :: inline (byte: u8) -> bool { + // BBBB BBBB & 1100 0000 == 10XX XXXX -> is continuation byte + return (byte & 0xC0) == 0x80; +} + +// Given a leading_byte, returns the number of bytes on the character. +count_character_bytes :: inline (leading_byte: u8) -> int { + // BBBB BBBB & 1110 0000 == 110X XXXX -> 1 initial + 1 continuation byte + if (leading_byte & 0xE0) == 0xC0 return 1+1; + + // BBBB BBBB & 1111 0000 == 1110 XXXX -> 1 initial + 2 continuation byte + if (leading_byte & 0xF0) == 0xE0 return 1+2; + + // BBBB BBBB & 1111 1000 == 1111 0XXX -> 1 initial + 3 continuation byte + if (leading_byte & 0xF8) == 0xF0 return 1+3; + + return 1; +} + +// Returns the string (using same str.data) truncated to the provided length. +truncate :: (str: string, length: int) -> string { + + if str.data == null then return ""; + + if str.count < length then return .{str.count, str.data}; + + data := str.data; + count := str.count; + + // Find index of first continuation byte. + idx := length; + while (idx > 0 && is_continuation_byte(data[idx - 1])) { + idx -= 1; + } + continuation_bytes := length - idx; + + // If string starts with continuation bytes, it's an invalid UTF8 string. + if (idx == 0 && continuation_bytes > 0) { + length = 0; + } + // If length truncates some continuation bytes, remove incomplete UTF8 character. + else if (idx > 0 // string is not empty + // continuation bytes are not complete + && !(continuation_bytes == 0 && (data[idx - 1] & 0x80) == 0x00) + && !(continuation_bytes == 1 && (data[idx - 1] & 0xE0) == 0xC0) + && !(continuation_bytes == 2 && (data[idx - 1] & 0xF0) == 0xE0) + && !(continuation_bytes == 3 && (data[idx - 1] & 0xF8) == 0xF0) + ) { + length -= (continuation_bytes + 1); // Remove start byte, hence '+ 1'. + } + + return .{length, str.data}; +} + +// Returns true when the string is empty or consists of space characters. +is_empty :: (str: string) -> bool { + for 0..str.count-1 { + if str[it] == { + case #char "\0"; #through; + case #char "\t"; #through; // horizontal tab + case #char "\n"; #through; // line feed + case #char "\x0B"; #through; // vertical tabulation + case #char "\x0C"; #through; // form feed + case #char "\r"; #through; // carriage return + case #char " "; + continue; + case; + return false; + } + } + return true; +} + +// Counts the number of characters. +count_characters :: (str: string, $is_null_terminated := false) -> int { + characters := 0; + idx := 0; + + #if is_null_terminated { + while idx < str.count && str[idx] != 0 { + idx += count_character_bytes(str[idx]); + characters += 1; + } + } + else { + while idx < str.count { + idx += count_character_bytes(str[idx]); + characters += 1; + } + } + + return characters; +} + +// Deletes character by it's index, and moves tail data to take its place. +delete_character :: (str: *string, character_idx: int) -> success := true { + buffer_idx := get_byte_index(str.*, character_idx); + + if buffer_idx < 0 return false; + + bytes_to_delete := count_character_bytes(str.data[buffer_idx]); + + for buffer_idx..str.count-1-bytes_to_delete { + str.data[it] = str.data[it+bytes_to_delete]; + } + for str.count-bytes_to_delete..str.count-1 { + str.data[it] = 0; + } + + str.count -= bytes_to_delete; + return; +} + +// Searches for the given character index and returns its byte index on the string. +get_byte_index :: (str: string, character_index: int) -> buffer_index: int, success := true { + buff_idx := 0; + char_idx := 0; + while buff_idx < str.count { + if char_idx == character_index return buff_idx; + buff_idx += count_character_bytes(str[buff_idx]); + char_idx += 1; + } + return -1, false; +} diff --git a/modules/UTF8/tests.jai b/modules/UTF8/tests.jai new file mode 100644 index 0000000..aff1d36 --- /dev/null +++ b/modules/UTF8/tests.jai @@ -0,0 +1,5 @@ +#import "Basic"; + +main :: () { + assert(false, "TODO"); // TODO +} diff --git a/sizeof.c b/sizeof.c deleted file mode 100644 index c260c31..0000000 --- a/sizeof.c +++ /dev/null @@ -1,50 +0,0 @@ -// compile with : gcc sizeof.c -lncurses - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int main(int argc, char **argv) { - // initscr(); - - fprintf(stderr, "sizeof char: %d\n", sizeof(char)); - fprintf(stderr, "sizeof short: %d\n", sizeof(short)); - fprintf(stderr, "sizeof int: %d\n", sizeof(int)); - fprintf(stderr, "sizeof long: %d\n", sizeof(long)); - fprintf(stderr, "sizeof unsigned: %d\n", sizeof(unsigned)); - fprintf(stderr, "sizeof chtype: %d\n", sizeof(chtype)); - // int w_size_x, w_size_y; - // getmaxyx(stdscr, w_size_y, w_size_x); - // char str[64]; - // memset(str, 0, 64); - // sprintf(str, "x,y : %dx%d\n", w_size_x, w_size_y); - // mvaddstr(2, 2, str); - // sprintf(str, "resize:%d\n", KEY_RESIZE); - // mvaddstr(3, 2, str); - - // unsigned m = ACS_DIAMOND; - fprintf(stderr, "sizeof ACS %d\n", sizeof(ACS_DIAMOND)); - // - // if (ACS_DIAMOND != 0 || ACS_URCORNER != 0){ - // fprintf(stderr, "BAZINGA\n"); - // } -// fprintf(stderr, ">%d<\n", strlen(ACS_DIAMOND)); - - // mvaddch(0, 0, m); - // getch(); - // endwin(); -} - diff --git a/ttt.jai b/ttt.jai index bb395fa..b0d60d0 100644 --- a/ttt.jai +++ b/ttt.jai @@ -7,7 +7,7 @@ DEBUG :: false; #import "File"; #import "File_Utilities"; #import "String"; -#import "Integer_Saturating_Arithmetic"; +#import "Saturation"; #import "UTF8"; TUI :: #import "TUI"(COLOR_MODE_BITS=4); -- cgit v1.2.3