// TODO
// replace writeToSelf to __..._write__
// todo try use __ScalpiTerminalInput_updateBuffer__ with __ScalpiTerminalInput_grab__ in one loop
// about
// licenze:
// This code and its derivatives can be used under the following conditions:
// - Do not attack other countries.
// - Jerk off on public at least 1 time per day.
// - Observe hygiene.
// - check my other projects https://chiselapp.com/user/sergey6661313
// about:
// ScalpiEditor - ansi-only text editor for terminals.
// killer features: no. its just editor.
// Compile:
// this file is just part of zig version (for now)
// current version used zig compiller for compile zig file. (unstructions inside zig file)
// in future you can use tcc for compile
// tcc se_windows.c
// to support me
// with boosty:
// https://boosty.to/cutloosedev
// with monero:
// 87T7 qGbA TrM3 a6Br
// DyeC jQQf NWtU u3iZ
// bHVB MC6W mEbN NE13
// Qrrt KhBb e4vF 58NR
// 8PTF dYk2 Sozc HexX
// 4Q69 jbdQ Asrs P7B
// enums and constants
// compilation target
// os
#define __TargetOs_windows__ 1
#define __TargetOs_linux__ 2
// memory type
#define __TargetMemoryType_endiansLittle__ 1
#define __TargetMemoryType_endiansBig__ 2
// time
#define Scalpi_time_ms_per_s 1000
// Scalpi_Logger_writers
#define Scalpi_Logger_writers_c_out_writer 0
#define Scalpi_Logger_writers_file_writer 1
#define Scalpi_Logger_writers_console_writer 2
#define Scalpi_Logger_writers_terminal_writer 3
// settings
// #define __target_os__ __TargetOs_
#ifndef __target_os__
#ifdef _WIN32
#define __target_os__ __TargetOs_windows__
#elif defined(__linux__)
#define __target_os__ __TargetOs_linux__
#endif
#endif
#if __target_os__ == __TargetOs_windows__
#elif __target_os__ == __TargetOs_linux__
#else
#error "__target_os__ not implemented"
#endif
#define __target_memory_type__ __TargetMemoryType_endiansLittle__
#define __ScalpiTerminalInput_size__ 32
// App
#define App_expected_fps 30
// imports
// libC
#include "stdarg.h"
#include "stdbool.h"
#include "stddef.h"
#include "stdint.h"
#include "stdio.h"
#include "stdlib.h"
#include "assert.h"
#include "ctype.h"
#include "errno.h"
#include "fenv.h"
#include "float.h"
#include "inttypes.h"
#include "iso646.h"
#include "limits.h"
#include "locale.h"
#include "math.h"
#include "setjmp.h"
#include "signal.h"
#include "string.h"
#include "tgmath.h"
#include "time.h"
#include "uchar.h"
#include "wchar.h"
#include "wctype.h"
#if __target_os__ == __TargetOs_windows__
// posix
#include "fcntl.h"
// Windows
#include "windef.h"
#include "windows.h"
#include "winuser.h"
#include "commctrl.h"
#include "io.h"
#include "conio.h"
// network
// #include "ws2tcpip.h"
// #include "winsock2.h"
#elif __target_os__ == __TargetOs_linux__
#include "sys/ioctl.h"
#include "termios.h"
#include "unistd.h"
#include <time.h>
// network
// #include "arpa/inet.h"
// #include "netinet/in.h"
// #include "netinet/ip.h"
// #include "sys/socket.h"
#endif
// strings
#define Scalpi_Text_CharsDecFromU64_MAX_LEN TEXT_LEN("18446744073709551615")
// Scalpi_Console_ansi
#define Scalpi_Console_ansi_esc "\x1B"
#define __ScalpiConsoleAnsi_control__ Scalpi_Console_ansi_esc "["
#define Scalpi_Console_ansi_output_clear_to_end_line __ScalpiConsoleAnsi_control__ "0K"
#define Scalpi_Console_ansi_output_clear_to_start_line __ScalpiConsoleAnsi_control__ "1K"
#define Scalpi_Console_ansi_output_clear_line __ScalpiConsoleAnsi_control__ "2K"
// cursor
#define Scalpi_Console_ansi_output_cursor_hide __ScalpiConsoleAnsi_control__ "?25l"
#define Scalpi_Console_ansi_output_cursor_show __ScalpiConsoleAnsi_control__ "?25h"
#define __ScalpiConsoleAnsiOutputCursorStyle_reset__ __ScalpiConsoleAnsi_control__ "0 q"
#define Scalpi_Console_ansi_output_cursor_style_blinking_block __ScalpiConsoleAnsi_control__ "1 q"
#define Scalpi_Console_ansi_output_cursor_style_steady_block __ScalpiConsoleAnsi_control__ "2 q"
#define Scalpi_Console_ansi_output_cursor_style_blinking_underline __ScalpiConsoleAnsi_control__ "3 q"
#define Scalpi_Console_ansi_output_cursor_style_steady_underline __ScalpiConsoleAnsi_control__ "4 q"
#define Scalpi_Console_ansi_output_cursor_style_blinking_I_beam __ScalpiConsoleAnsi_control__ "5 q"
#define Scalpi_Console_ansi_output_cursor_style_steady_I_beam __ScalpiConsoleAnsi_control__ "6 q"
// color
#define Scalpi_Console_ansi_output_FontStyle_color_zero "39"
#define Scalpi_Console_ansi_output_FontStyle_color_black "30"
#define Scalpi_Console_ansi_output_FontStyle_color_red "31"
#define Scalpi_Console_ansi_output_FontStyle_color_green "32"
#define Scalpi_Console_ansi_output_FontStyle_color_gold "33"
#define Scalpi_Console_ansi_output_FontStyle_color_blue "34"
#define Scalpi_Console_ansi_output_FontStyle_color_magenta "35"
#define Scalpi_Console_ansi_output_FontStyle_color_cyan "36"
#define Scalpi_Console_ansi_output_FontStyle_color_light_gray "37"
#define Scalpi_Console_ansi_output_FontStyle_color_gray "90"
#define Scalpi_Console_ansi_output_FontStyle_color_pink "91"
#define Scalpi_Console_ansi_output_FontStyle_color_light_green "92"
#define Scalpi_Console_ansi_output_FontStyle_color_yellow "93"
#define Scalpi_Console_ansi_output_FontStyle_color_light_blue "94"
#define Scalpi_Console_ansi_output_FontStyle_color_light_magenta "95"
#define Scalpi_Console_ansi_output_FontStyle_color_light_cyan "96"
#define Scalpi_Console_ansi_output_FontStyle_color_white "97"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_zero "49"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_black "40"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_red "41"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_green "42"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_gold "43"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_blue "44"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_magenta "45"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_cyan "46"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_gray "47"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_gray "100"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_pink "101"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_green "102"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_yellow "103"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_blue "104"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_magenta "105"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_light_cyan "106"
#define Scalpi_Console_ansi_output_FontStyle_bg_color_white "107"
#define Scalpi_Console_ansi_output_FontStyle_sep ";"
#define Scalpi_Console_ansi_output_FontStyle_end "m"
#define Scalpi_Console_ansi_output_FontStyle_reset "0"
#define Scalpi_Console_ansi_output_FontStyle_bold "1"
#define Scalpi_Console_ansi_output_FontStyle_dim "2"
#define Scalpi_Console_ansi_output_FontStyle_italic "3"
#define Scalpi_Console_ansi_output_FontStyle_underline "4"
#define Scalpi_Console_ansi_output_FontStyle_conceal "8"
#define Scalpi_Console_ansi_output_FontStyle_fraktur "20"
#define Scalpi_Console_ansi_output_FontStyle_unbold "21;24"
#define Scalpi_Console_ansi_output_FontStyle_set_color "38"
#define Scalpi_Console_ansi_output_FontStyle_set_bg_color "48"
#define Scalpi_Console_ansi_output_FontStyle_start __ScalpiConsoleAnsi_control__
#define __ScalpiConsoleAnsiOutputFontStyle_reset__ Scalpi_Console_ansi_output_FontStyle_start Scalpi_Console_ansi_output_FontStyle_reset Scalpi_Console_ansi_output_FontStyle_end
// mouse
#define Scalpi_ansi_input_mouse_release __ScalpiConsoleAnsi_control__ "?1000l"
#define Scalpi_ansi_input_mouse_grab __ScalpiConsoleAnsi_control__ "?1000h"
#define __ScalpiConsoleAnsiOutputSettings_enableLineWrap__ __ScalpiConsoleAnsi_control__ "?7h"
#define __ScalpiConsoleAnsiOutputSettings_disableLineWrap__ __ScalpiConsoleAnsi_control__ "?7l"
// const Scalpi_Console_ansi_input_Key
// ascii
#define __Scalpi_Console_ansi_input_Key_ascii_ctrl__ (-'a' + 1) /* do not use externally */
#define __Scalpi_Console_ansi_input_Key_ctrl_bs__ 8 /* also ctrl_h */
#define __Scalpi_Console_ansi_input_Key_tab__ 9 /* also ctrl_i */
#define __Scalpi_Console_ansi_input_Key_enter__ 13 /* also ctrl_m */
#define __Scalpi_Console_ansi_input_Key_escape__ 27
#define __Scalpi_Console_ansi_input_Key_back_space__ 127 /* sometime delete */
#define __Scalpi_Console_ansi_input_Key_ctrl_a__ ('a' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 1 start_of_heading */
#define __Scalpi_Console_ansi_input_Key_ctrl_b__ ('b' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 2 */
#define __Scalpi_Console_ansi_input_Key_ctrl_c__ ('c' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 3 */
#define __Scalpi_Console_ansi_input_Key_ctrl_d__ ('d' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 4 */
#define __Scalpi_Console_ansi_input_Key_ctrl_e__ ('e' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 5 */
#define __Scalpi_Console_ansi_input_Key_ctrl_f__ ('f' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 6 */
#define __Scalpi_Console_ansi_input_Key_ctrl_g__ ('g' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 7 */
#define __Scalpi_Console_ansi_input_Key_ctrl_h__ ('h' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 8 also */ ctrl_bs */
#define __Scalpi_Console_ansi_input_Key_ctrl_i__ ('i' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 9 also */ tab */
#define __Scalpi_Console_ansi_input_Key_ctrl_j__ ('j' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 10 */
#define __Scalpi_Console_ansi_input_Key_ctrl_k__ ('k' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 11 vertical_tab */ */
#define __Scalpi_Console_ansi_input_Key_ctrl_l__ ('l' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 12 formFeed */ */
#define __Scalpi_Console_ansi_input_Key_ctrl_m__ ('m' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 13 also */ enter */
#define __Scalpi_Console_ansi_input_Key_ctrl_n__ ('n' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 14 */
#define __Scalpi_Console_ansi_input_Key_ctrl_o__ ('o' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 15 */
#define __Scalpi_Console_ansi_input_Key_ctrl_p__ ('p' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 16 */
#define __Scalpi_Console_ansi_input_Key_ctrl_q__ ('q' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 17 */
#define __Scalpi_Console_ansi_input_Key_ctrl_r__ ('r' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 18 */
#define __Scalpi_Console_ansi_input_Key_ctrl_s__ ('s' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 19 */
#define __Scalpi_Console_ansi_input_Key_ctrl_t__ ('t' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 20 */
#define __Scalpi_Console_ansi_input_Key_ctrl_u__ ('u' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 21 */
#define __Scalpi_Console_ansi_input_Key_ctrl_v__ ('v' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 22 */
#define __Scalpi_Console_ansi_input_Key_ctrl_w__ ('w' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 23 */
#define __Scalpi_Console_ansi_input_Key_ctrl_x__ ('x' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 24 */
#define __Scalpi_Console_ansi_input_Key_ctrl_y__ ('y' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 25 */
#define __Scalpi_Console_ansi_input_Key_ctrl_z__ ('z' + __Scalpi_Console_ansi_input_Key_ascii_ctrl__) /* 26 */
// __Scalpi_Console_ansi_input_Key_non_ascii__
#define __Scalpi_Console_ansi_input_Key_special__ (1 << 8)
#define __Scalpi_Console_ansi_input_Key_functional__ (1 << 9)
#define __Scalpi_Console_ansi_input_Key_ctrl__ (1 << 10)
#define __Scalpi_Console_ansi_input_Key_alt__ (1 << 11)
#define __Scalpi_Console_ansi_input_Key_shift__ (1 << 12)
#define __Scalpi_Console_ansi_input_Key_mouse__ (1 << 13)
// FN
#define __Scalpi_Console_ansi_input_Key_f1__ (1 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f2__ (2 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f3__ (3 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f4__ (4 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f5__ (5 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f6__ (6 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f7__ (7 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f8__ (8 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f9__ (9 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f10__ (10 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f11__ (11 + __Scalpi_Console_ansi_input_Key_functional__)
#define __Scalpi_Console_ansi_input_Key_f12__ (12 + __Scalpi_Console_ansi_input_Key_functional__)
// arrows
// left
#define __Scalpi_Console_ansi_input_Key_left__ (1 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_left__ (__Scalpi_Console_ansi_input_Key_left__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_alt_left__ (__Scalpi_Console_ansi_input_Key_left__ + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_shift_left__ (__Scalpi_Console_ansi_input_Key_left__ + __Scalpi_Console_ansi_input_Key_shift__)
#define __Scalpi_Console_ansi_input_Key_ctrl_shift_left__ (__Scalpi_Console_ansi_input_Key_left__ + __Scalpi_Console_ansi_input_Key_ctrl__ + __Scalpi_Console_ansi_input_Key_shift__)
// right
#define __Scalpi_Console_ansi_input_Key_right__ (2 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_right__ (__Scalpi_Console_ansi_input_Key_right__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_alt_right__ (__Scalpi_Console_ansi_input_Key_right__ + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_shift_right__ (__Scalpi_Console_ansi_input_Key_right__ + __Scalpi_Console_ansi_input_Key_shift__)
#define __Scalpi_Console_ansi_input_Key_ctrl_shift_right__ (__Scalpi_Console_ansi_input_Key_right__ + __Scalpi_Console_ansi_input_Key_ctrl__ + __Scalpi_Console_ansi_input_Key_shift__)
// up
#define __Scalpi_Console_ansi_input_Key_up__ (3 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_up__ (__Scalpi_Console_ansi_input_Key_up__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_alt_up__ (__Scalpi_Console_ansi_input_Key_up__ + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_shift_up__ (__Scalpi_Console_ansi_input_Key_up__ + __Scalpi_Console_ansi_input_Key_shift__)
// down
#define __Scalpi_Console_ansi_input_Key_down__ (4 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_down__ (__Scalpi_Console_ansi_input_Key_down__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_alt_down__ (__Scalpi_Console_ansi_input_Key_down__ + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_shift_down__ (__Scalpi_Console_ansi_input_Key_down__ + __Scalpi_Console_ansi_input_Key_shift__)
// spec keys
#define __Scalpi_Console_ansi_input_Key_delete__ (5 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_shift_delete__ (__Scalpi_Console_ansi_input_Key_delete__ + __Scalpi_Console_ansi_input_Key_shift__)
#define __Scalpi_Console_ansi_input_Key_page_up__ (6 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_page_down__ (7 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_end__ (8 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_home__ (9 + __Scalpi_Console_ansi_input_Key_special__)
#define __Scalpi_Console_ansi_input_Key_ctrl_enter__ (__Scalpi_Console_ansi_input_Key_enter__ + __Scalpi_Console_ansi_input_Key_special__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_ctrl_triangular_open_quotation_mark__ ('<' + __Scalpi_Console_ansi_input_Key_special__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_ctrl_triangular_close_quotation_mark__ ('>' + __Scalpi_Console_ansi_input_Key_special__ + __Scalpi_Console_ansi_input_Key_ctrl__)
#define __Scalpi_Console_ansi_input_Key_ctrl_alt_v__ ('v' + __Scalpi_Console_ansi_input_Key_alt__ + __Scalpi_Console_ansi_input_Key_ctrl__)
// altX
#define __Scalpi_Console_ansi_input_Key_alt_a__ ('a' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_b__ ('b' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_c__ ('c' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_d__ ('d' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_e__ ('e' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_f__ ('f' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_g__ ('g' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_h__ ('h' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_i__ ('i' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_j__ ('j' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_k__ ('k' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_l__ ('l' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_m__ ('m' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_n__ ('n' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_o__ ('o' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_p__ ('p' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_q__ ('q' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_r__ ('r' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_s__ ('s' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_t__ ('t' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_u__ ('u' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_v__ ('v' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_w__ ('w' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_x__ ('x' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_y__ ('y' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_z__ ('z' + __Scalpi_Console_ansi_input_Key_alt__)
// alt_shiftX,
#define __Scalpi_Console_ansi_input_Key_alt_M__ ('M' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_N__ ('N' + __Scalpi_Console_ansi_input_Key_alt__)
// altN
#define __Scalpi_Console_ansi_input_Key_alt_0__ ('0' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_1__ ('1' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_2__ ('2' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_3__ ('3' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_4__ ('4' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_5__ ('5' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_6__ ('6' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_7__ ('7' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_8__ ('8' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_9__ ('9' + __Scalpi_Console_ansi_input_Key_alt__)
// alt_spec
#define __Scalpi_Console_ansi_input_Key_alt_comma__ (',' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_dot__ ('.' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_open_bracket__ ('[' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_close_bracket__ (']' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_semicolon__ (';' + __Scalpi_Console_ansi_input_Key_alt__)
#define __Scalpi_Console_ansi_input_Key_alt_apostrophe__ ('`' + __Scalpi_Console_ansi_input_Key_alt__)
// __OsFilePath_separator__
#if __target_os__ == __TargetOs_windows__
#define __OsFilePath_separator__ "\\"
#elif __target_os__ == __TargetOs_linux__
#define __OsFilePath_separator__ "/"
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
// basic types
// scalpi
typedef uint8_t* __AlignedPtr__;
typedef uint64_t __ScalpiConsoleAnsiInputKey__;
typedef size_t (*__WriteFnPtr__) (void* context, const char* bytes, size_t bytes_len);
typedef void (*__WriteFnPtrVoid__) (void* context, const char* bytes, size_t bytes_len);
// OS
// Os_Console_Input_Handle
#if __target_os__ == __TargetOs_windows__
typedef void* Os_Console_Input_Handle;
#elif __target_os__ == __TargetOs_linux__
typedef FILE* Os_Console_Input_Handle;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
// __OsConsoleOutputHandle__
#if __target_os__ == __TargetOs_windows__
typedef void* __OsConsoleOutputHandle__;
#elif __target_os__ == __TargetOs_linux__
typedef FILE* __OsConsoleOutputHandle__;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
// macroses
// c
#define __VAR__
#define or ||
#define and &&
#define OFFSETOF(type, field) ((size_t) &(((type *)0)->field))
#define FIELD_PARENT_PTR(type, field, instance) ((type *)((char *)(instance) - OFFSETOF(type, field)))
#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
#define TEXT_LEN(str) (ARRAY_LEN(str) - 1)
#define toAddr(ptr) ((uintptr_t)(ptr))
#define getField(ptr, offset, type) (* (*type) ( toAddr(ptr) + offset ) )
// text
#define SLICE_TEXT(text) {.ptr=text, .len=TEXT_LEN(text)}
#define TEXT_PTR(text) (char(*)[TEXT_LEN(text)]) text
#define DEF_TEXT_PTR(name, text) char(*name)[TEXT_LEN(text)] = TEXT_PTR(text)
#define DEF_SLICE_TEXT(name, text) struct Slice name = SLICE_TEXT(text)
// App
#define App_delay_to_start_frame_target (Scalpi_time_ms_per_s / App_expected_fps)
// structs
// core
// memory
struct Slice {
char* ptr;
size_t len;
};
struct Finder {
struct Slice text;
struct Slice desired;
size_t pos;
};
// Os
#if __target_os__ == __TargetOs_windows__
#elif __target_os__ == __TargetOs_linux__
struct __OsLinux_timespec__ {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#else
#error "__target_os__ not implemented"
#endif
// OsConsole
struct __OsConsoleFlags__ {
bool inited;
#if __target_os__ == __TargetOs_windows__
DWORD input_mode;
DWORD output_mode;
#elif __target_os__ == __TargetOs_linux__
struct termios termios;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
};
struct Os_Console_Input {
Os_Console_Input_Handle handle;
#if __target_os__ == __TargetOs_windows__
#elif __target_os__ == __TargetOs_linux__
int fileno;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
};
struct __OsConsoleOutput__ {
#if __target_os__ == __TargetOs_windows__
__OsConsoleOutputHandle__ __OsConsoleOutput_handle__;
#elif __target_os__ == __TargetOs_linux__
__OsConsoleOutputHandle__ __OsConsoleOutput_handle__;
int __OsConsoleOutput_fileno__;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
};
struct __OsHelper__ {
bool network_inited;
#if __target_os__ == __TargetOs_windows__
HINSTANCE instance;
void* console_input_handle;
void* console_output_handle;
WSADATA wsdata;
#elif __target_os__ == __TargetOs_linux__
FILE* console_input_handle;
FILE* console_output_handle;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
};
// Scalpi
// math
struct __Scalpi_math_d2_U_Pos__ {
size_t x;
size_t y;
};
// text
struct Scalpi_Text_Splitter {
struct Finder finder;
bool stop;
size_t last_pos;
};
struct __Scalpi_Writer__ {
void* context;
__WriteFnPtr__ write;
};
struct Scalpi_Logger {
// write to terminal, console, file or to all together, but no real check "bytes is writen"
struct __Scalpi_Writer__ writers[4] // Scalpi_Logger_writers
};
// Console
// __Scalpi_Console_ansi_input_Key_SequenceParser__
struct __Scalpi_Console_ansi_input_Key_SequenceParser__ {
__ScalpiConsoleAnsiInputKey__ sequence;
size_t used;
};
struct Scalpi_Console_ansi_input_Key_SequenceParser_fromBytes_SequenceInfo {
const char* text;
size_t len;
__ScalpiConsoleAnsiInputKey__ key;
};
struct __ScalpiConsole__ {
struct Os_Console_Input input;
struct __OsConsoleOutput__ output;
};
// Terminal
typedef struct __Scalpi_math_d2_U_Pos__ __ScalpiTerminalOutput_CursorPos__;
struct __ScalpiTerminalOutput__ {
__ScalpiTerminalOutput_CursorPos__ cursor_pos;
const char* font_style;
struct __Scalpi_math_d2_U_Pos__ size;
bool convert_n_to_rn;
bool apply_r;
bool apply_n;
};
struct __ScalpiTerminalInput__ {
// usage:
// call __ScalpiTerminalInput_updateBuffer__ for update unreaded
// use __ScalpiTerminalInput_grab__ in loop for get keys
size_t ungrabed;
char buffer[__ScalpiTerminalInput_size__];
};
struct __ScalpiTerminal__ {
struct __ScalpiConsole__ *console;
struct __OsConsoleFlags__ system_flags;
struct __ScalpiTerminalInput__ input;
struct __ScalpiTerminalOutput__ output;
};
// App
struct App {
struct __OsHelper__ __App_osHelper__;
struct Scalpi_Logger logger;
uint64_t tick;
};
// function prototypes
size_t __OsFallbackConsole_write__(void* unused_ctx, char* data, size_t len);
// globals
struct App global_app;
// functions
// core
// mem
// bits operations
uint8_t bits_rotl8(uint8_t value, unsigned int shift) {
shift %= 8;
return (value << shift) | (value >> (8 - shift));
}
uint16_t bits_rotl16(uint16_t value, unsigned int shift) {
shift %= 16;
return (value << shift) | (value >> (16 - shift));
}
uint32_t bits_rotl32(uint32_t value, unsigned int shift) {
shift %= 32;
return (value << shift) | (value >> (32 - shift));
}
uint64_t bits_rotl64(uint64_t value, unsigned int shift) {
shift %= 64;
return (value << shift) | (value >> (64 - shift));
}
// bytes operations
size_t Scalpi_mem_fill(char* dest, char symbol, size_t len) {
for (size_t pos = 0; pos < len; pos++) {
dest[pos] = symbol;
}
}
void __ScalpiMem_copy__(char* dest, const char* src, size_t size) {
// i use this instead memcpy becouse clang-in-zig just replace memcpy to crash-zig-bloated-version code
size_t pos;
for(pos = 0; pos < size; pos++) {
dest[pos] = src[pos];
}
}
bool Scalpi_mem_isEql(const char a[], const char b[], size_t len) {
for(size_t pos = 0; pos < len; pos ++) {
char ac = a[pos];
char bc = b[pos];
if (ac != bc) return false;
}
return true;
}
void writeWithOffset(char* dest, size_t* writed, char* data, size_t data_len) {
__ScalpiMem_copy__(&dest[*writed], data, data_len);
*writed += data_len;
}
// format_number
// copy non aligned data
void memcpy2(char* dest, char* src) {
dest[0] = src[0];
dest[1] = src[1];
}
void memcpy4(char* dest, char* src) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
}
void memcpy8(char* dest, char* src) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest[4] = src[4];
dest[5] = src[5];
dest[6] = src[6];
dest[7] = src[7];
}
// swap bytes for converting endians
void swapBytes16(char* a, char* b) {
// b is output
b[0] = a[1];
b[1] = a[0];
}
void swapBytes32(char* a, char* b) {
// b is output
b[0] = a[3];
b[1] = a[2];
b[2] = a[1];
b[3] = a[0];
}
void swapBytes64(char* a, char* b) {
// b is output
b[0] = a[7];
b[1] = a[6];
b[2] = a[5];
b[3] = a[4];
b[4] = a[3];
b[5] = a[2];
b[6] = a[1];
b[7] = a[0];
}
bool cpu_checkNumberFormat() {
char current_endians = 0;
int n = 1;
if (* (char *) &n == 1) {
current_endians = __TargetMemoryType_endiansLittle__;
} else {
current_endians = __TargetMemoryType_endiansBig__;
}
if (__target_memory_type__ == current_endians) {
return true;
} else {
printf("%d wrong MEMORY_TYPE !\r\n", __LINE__);
}
return false;
}
#if __target_memory_type__ == __TargetMemoryType_endiansBig__
#define nativeToBig16(src, dest) memcpy2(dest, src)
#define nativeToBig32(src, dest) memcpy4(dest, src)
#define nativeToBig64(src, dest) memcpy8(dest, src)
#define nativeToLittle16(src, dest) swapBytes16(src, dest)
#define nativeToLittle32(src, dest) swapBytes32(src, dest)
#define nativeToLittle64(src, dest) swapBytes64(src, dest)
#elif __target_memory_type__ == __TargetMemoryType_endiansLittle__
#define nativeToBig16(src, dest) swapBytes16(src, dest)
#define nativeToBig32(src, dest) swapBytes32(src, dest)
#define nativeToBig64(src, dest) swapBytes64(src, dest)
#define nativeToLittle16(src, dest) memcpy2(dest, src)
#define nativeToLittle32(src, dest) memcpy4(dest, src)
#define nativeToLittle64(src, dest) memcpy8(dest, src)
#else
#error "please define __target_memory_type__ with __TargetMemoryType_ (you can test endings with cpu_checkNumberFormat function)"
#endif
// read unaligned memory
// big
uint16_t readBig16(char* src) {
uint16_t ret;
nativeToBig16(src, (char*) &ret);
return ret;
}
uint32_t readBig32(char* src) {
uint32_t ret;
nativeToBig32(src, (char*) &ret);
return ret;
}
uint64_t readBig64(char* src) {
uint64_t ret;
nativeToBig64(src, (char*) &ret);
return ret;
}
// little
uint16_t readLittle16(char* src) {
uint16_t ret;
nativeToLittle16(src, (char*) &ret);
return ret;
}
uint32_t readLittle32(char* src) {
uint32_t ret;
nativeToLittle32(src, (char*) &ret);
return ret;
}
uint64_t readLittle64(char* src) {
uint64_t ret;
nativeToLittle64(src, (char*) &ret);
return ret;
}
// write unaligned memory
// big
void writeBig16(uint16_t value, char* dest) {
nativeToBig16((char*)&value, dest);
}
void writeBig32(uint32_t value, char* dest) {
nativeToBig32((char*)&value, dest);
}
void writeBig64(uint64_t value, char* dest) {
nativeToBig64((char*)&value, dest);
}
// little
void writeLittle16(uint16_t value, char* dest) {
nativeToLittle16((char*)&value, dest);
}
void writeLittle32(uint32_t value, char* dest) {
nativeToLittle32((char*)&value, dest);
}
void writeLittle64(uint64_t value, char* dest) {
nativeToLittle64((char*)&value, dest);
}
// Slice
void Slice_debug(struct Slice* slice, char* name, size_t line) {
if (slice->len == 0) {
printf("%zu: %s is NULL. \r\n", line, name);
} else {
printf("%zu: %s (%zu): \"%.*s", line, name, slice->len, (int)slice->len, slice->ptr);
}
}
bool Scalpi_mem_find(struct Slice* slice, struct Slice* desired, uintptr_t* out_pos) {
// not fast
if (slice->len >= desired->len) {
uintptr_t last_pos = slice->len - desired->len;
for (uintptr_t pos = 0; pos <= last_pos; pos++) {
size_t slice_len = slice->len - pos;
if (slice_len >= desired->len) {
if (Scalpi_mem_isEql(&slice->ptr[pos], desired->ptr, desired->len)) {
*out_pos = pos;
return true;
}
} else {
break;
}
}
} else {
// printf("%d desired is too long\r\n", __LINE__);
}
return false;
}
bool isStartWith(struct Slice* a, struct Slice* b) {
return (a->len >= b->len) && Scalpi_mem_isEql(a->ptr, b->ptr, b->len);
}
// Finder
void Finder_init(struct Finder* t, char* text, size_t text_len, char* desired, size_t desired_len) {
t->pos = 0;
t->text.ptr = text;
t->text.len = text_len;
t->desired.ptr = desired;
t->desired.len = desired_len;
}
bool Finder_next(struct Finder* t, size_t* out_pos) {
if (t->pos != t->text.len) {
struct Slice slice; // = t->text[->.pos..];
slice.ptr = &t->text.ptr[t->pos];
slice.len = t->text.len - t->pos;
size_t finded;
if (Scalpi_mem_find(&slice, &t->desired, &finded)) {
size_t new_pos = t->pos + finded;
t->pos = new_pos + t->desired.len;
*out_pos = new_pos;
return true;
}
}
return false;
}
// text Splitter
void Scalpi_Text_Splitter_init(struct Scalpi_Text_Splitter* t, char* text, size_t text_len, char* delim, size_t delim_len) {
t->stop = false;
t->last_pos = 0;
Finder_init(&t->finder, text, text_len, delim, delim_len);
}
bool Scalpi_Text_Splitter_next(struct Scalpi_Text_Splitter* t, struct Slice* out_slice) {
if (t->stop == false) {
size_t finded;
if (Finder_next(&t->finder, &finded)) {
out_slice->ptr = &t->finder.text.ptr[t->last_pos]; // slice = t->finder.text[t->last_pos..finded];
out_slice->len = finded - t->last_pos;
t->last_pos = t->finder.pos;
return true;
} else {
t->stop = true;
out_slice->ptr = &t->finder.text.ptr[t->last_pos]; // slice = t->finder.text[t->last_pos..];
out_slice->len = t->finder.text.len - t->last_pos;
t->last_pos = t->finder.pos;
return true;
}
}
return false;
}
// math
uint32_t ceilDiv32(uint32_t a, uint32_t b) {
return (a + b - 1) / b;
}
// Scalpi_Text_writeU64AsText
size_t Scalpi_Text_writeU64AsTextToBuffer(char buffer[], uint64_t number, size_t min_width) { // utoa utos
size_t writed = 0;
// write number to tmp
char buffer_tmp[Scalpi_Text_CharsDecFromU64_MAX_LEN];
uintptr_t tmp_ptr = (uintptr_t) &buffer_tmp[0] + Scalpi_Text_CharsDecFromU64_MAX_LEN;
for (uint64_t num = number; num > 0; num = num / 10) {
uint8_t remainder = num % 10;
tmp_ptr--;
*(char*)tmp_ptr = '0' + (char) remainder;
}
const uintptr_t writed_tmp = (uintptr_t) &buffer_tmp[0] + Scalpi_Text_CharsDecFromU64_MAX_LEN - (uintptr_t) tmp_ptr;
// fill zeroes to min_width
size_t extra_fill = 0;
if (min_width > writed_tmp) {
extra_fill = min_width - writed_tmp;
writed += Scalpi_mem_fill(&buffer[0], '0', extra_fill);
}
if (writed_tmp > 0) {
__ScalpiMem_copy__(&buffer[writed], (char*)tmp_ptr, writed_tmp);
writed += writed_tmp;
}
return writed;
}
size_t __ScalpiText_writeU64AsTextToWriteFnVoid__(__WriteFnPtrVoid__ write, void* context, uint64_t number, size_t min_width) {
char buffer_tmp[Scalpi_Text_CharsDecFromU64_MAX_LEN];
const size_t writed = Scalpi_Text_writeU64AsTextToBuffer(&buffer_tmp[0], number, min_width);
write(context, buffer_tmp, writed);
return writed;
}
// C_Text
size_t C_Text_getLen(const char text[]) {
size_t len = 0;
while(text[len] != 0) len++;
return len;
}
size_t C_Text_writeToBuffer(char buffer[], char data[]) {
const size_t len = C_Text_getLen(data);
__ScalpiMem_copy__(buffer, data, len);
return len;
}
size_t C_Text_writeToWriteFn(__WriteFnPtr__ write, void* context, const char text[]) {
const size_t len = C_Text_getLen(text);
return write(context, text, len);
}
// Os
bool __Os_writeHome__(char* buffer, size_t space, size_t* ret_writed) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
char* home_drive = getenv("HOMEDRIVE");
char* home_path = getenv("HOMEPATH");
// get len
size_t home_drive_len = C_Text_getLen(home_drive);
size_t home_path_len = C_Text_getLen(home_path);
size_t len = 0
+ home_drive_len
+ home_path_len
;
if (space >= len) {
size_t writed = 0;
__ScalpiMem_copy__(&buffer[writed], home_drive, home_drive_len);
writed += home_drive_len;
__ScalpiMem_copy__(&buffer[writed], home_path, home_path_len);
writed += home_path_len;
if (len == writed) {
*ret_writed += len;
} else {
ok = false;
// print "{line} PATH={buffer:buffer_len}\n\n\n"
__ScalpiText_writeU64AsTextToWriteFnVoid__((__WriteFnPtrVoid__)&__OsFallbackConsole_write__, NULL, __LINE__, 1);
__OsFallbackConsole_write__(NULL, " ", 3);
__ScalpiText_writeU64AsTextToWriteFnVoid__((__WriteFnPtrVoid__)&__OsFallbackConsole_write__, NULL, len, 1);
__OsFallbackConsole_write__(NULL, " ", 3);
__OsFallbackConsole_write__(NULL, "PATH=", 5);
__OsFallbackConsole_write__(NULL, buffer, len);
__OsFallbackConsole_write__(NULL, "\n\n\n", 3);
}
} else {
ok = false;
// print "{line} need {len} space\r\n"
__ScalpiText_writeU64AsTextToWriteFnVoid__((__WriteFnPtrVoid__)&__OsFallbackConsole_write__, NULL, __LINE__, 1);
__OsFallbackConsole_write__(NULL, "need ", 0);
__ScalpiText_writeU64AsTextToWriteFnVoid__((__WriteFnPtrVoid__)&__OsFallbackConsole_write__, NULL, len, 1);
__OsFallbackConsole_write__(NULL, " space\r\n ", 0);
}
#elif __target_os__ == __TargetOs_linux__
char* home = getenv("HOME");
size_t len = C_Text_getLen(home);
if (space >= len) {
__ScalpiMem_copy__(buffer, home, len);
*ret_writed += len;
} else {
ok = false;
}
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
// time
uint64_t __os_getTick__() {
#if __target_os__ == __TargetOs_windows__
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
uint64_t ft64;
memcpy8((char*) &ft64, (void*)&ft);
return ft64 / 10000; // in ft is intervals * 100 ns. to ms need * 100 / 1000000
#elif __target_os__ == __TargetOs_linux__
// NOT TESTED
struct __OsLinux_timespec__ ts;
clock_gettime(CLOCK_REALTIME, (void*)&ts);
uint64_t ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
return ms;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
void Os_sleep(uint64_t ms) {
#if __target_os__ == __TargetOs_windows__
Sleep(ms);
#elif __target_os__ == __TargetOs_linux__
// NOT TESTED
struct __OsLinux_timespec__ delay;
delay.tv_sec = ms / 1000;
delay.tv_nsec = (ms % 1000) * 1000000;
nanosleep(&delay, NULL);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// Console
// ConsoleOutput
// __VAR__ __OsConsoleOutput_getSize__
void __OsConsoleOutput_getSize__ (
struct __OsConsoleOutput__ *t,
struct __Scalpi_math_d2_U_Pos__ *ret_pos
) {
#if __target_os__ == __TargetOs_windows__
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(t->__OsConsoleOutput_handle__, &csbi);
ret_pos->x = csbi.dwSize.X;
ret_pos->y = csbi.dwSize.Y;
#elif __target_os__ == __TargetOs_linux__
struct winsize w;
ioctl(t->__OsConsoleOutput_fileno__, TIOCGWINSZ, &w);
ret_pos->x = w.ws_col;
ret_pos->y = w.ws_row;
#else
#error "__target_os__ not implemented"
#endif
}
// __VAR__ __OsConsoleOutput_init__
void __OsConsoleOutput_init__(struct __OsConsoleOutput__* output, __OsConsoleOutputHandle__ handle) {
#if __target_os__ == __TargetOs_windows__
output->__OsConsoleOutput_handle__ = handle;
#elif __target_os__ == __TargetOs_linux__
output->__OsConsoleOutput_handle__ = handle;
output->__OsConsoleOutput_fileno__ = fileno(handle);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// __VAR__ __OsConsoleOutput_write__
size_t __OsConsoleOutput_write__(struct __OsConsoleOutput__* os_console_output, const char* data, size_t _len) {
bool ok = true;
// support null-string // todo remove me
size_t len = _len;
if (len == 0) {
while(data[len] != 0) len += 1;
}
#if __target_os__ == __TargetOs_windows__
unsigned long writed = 0;
WriteConsoleA(os_console_output->__OsConsoleOutput_handle__, data, len, &writed, NULL);
len = writed;
#elif __target_os__ == __TargetOs_linux__
// TODO rewrite to use native calls but before remove all buffered calling
if (fflush(os_console_output->__OsConsoleOutput_handle__) == 0) { // success == 0. flush all other buffers like printf.
if (fwrite(data, 1, len, os_console_output->__OsConsoleOutput_handle__) == len) {
if (fflush(os_console_output->__OsConsoleOutput_handle__) == 0) { // success == 0. flush all other buffers like printf.
} else {
ok = false;
}
} else {
ok = false;
}
} else {
ok = false;
}
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return len; // todo return ok;
}
// ConsoleIntput
bool __OsConsoleInput_readByte__(struct Os_Console_Input* t, char* byte) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
INPUT_RECORD key;
DWORD picked = 0;
if ( ReadConsoleInputA(t->handle, &key, 1, &picked) ) {
if (picked != 0) {
if (key.EventType == KEY_EVENT) {
KEY_EVENT_RECORD *event = &key.Event.KeyEvent;
if (event->bKeyDown != 0) {
if (event->uChar.AsciiChar != 0) {
*byte = event->uChar.AsciiChar;
} else {ok = false;}
} else {ok = false;}
} else {ok = false;}
} else {ok = false;}
} else {ok = false;}
#elif __target_os__ == __TargetOs_linux__
ssize_t result = read(t->fileno, byte, 1);
if (result != 1) {ok = false;}
#else
#error "__target_os__ not implemented"
#endif
return ok;
}
bool __OsConsoleInput_getCountOfUnreaded__(struct Os_Console_Input* t, size_t *ret_unreaded) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
DWORD unreaded = 0;
if ( GetNumberOfConsoleInputEvents(t->handle, &unreaded) ) {
*ret_unreaded += unreaded;
} else {
ok = false;
}
#elif __target_os__ == __TargetOs_linux__
int unreaded = 0;
int result = ioctl(t->fileno, FIONREAD, &unreaded);
*ret_unreaded += unreaded;
#else
#error "__target_os__ not implemented"
#endif
return ok;
}
void __OsConsoleInput_init__(struct Os_Console_Input* t, Os_Console_Input_Handle input_hanle) {
#if __target_os__ == __TargetOs_windows__
t->handle = input_hanle;
#elif __target_os__ == __TargetOs_linux__
t->handle = input_hanle;
t->fileno = fileno(t->handle);
#else
#error "__target_os__ not implemented"
#endif
}
// Flags
uint32_t __ScalpiBitsU32_enable__(uint32_t value, uint32_t mask) {
return value | mask;
}
uint32_t __ScalpiBitsU32_disable__(uint32_t value, uint32_t mask) {
return value & (~mask);
}
uint32_t __ScalpiBitsU32_toggle__(uint32_t value, uint32_t mask, bool new_state) {
if (new_state) {
return __ScalpiBitsU32_enable__(value, mask);
} else {
return __ScalpiBitsU32_disable__(value, mask);
}
}
bool __OsConsoleFlags_setNonCanonicalMode__(struct __OsConsoleFlags__ *t) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
uint32_t input = t->input_mode;
input = __ScalpiBitsU32_toggle__(input, ENABLE_EXTENDED_FLAGS, true);
input = __ScalpiBitsU32_toggle__(input, ENABLE_ECHO_INPUT, false); // print pressed keys
input = __ScalpiBitsU32_toggle__(input, ENABLE_LINE_INPUT, false); // wait '\n' (buffering on enter)
input = __ScalpiBitsU32_toggle__(input, ENABLE_VIRTUAL_TERMINAL_INPUT, true);
input = __ScalpiBitsU32_toggle__(input, ENABLE_PROCESSED_INPUT, false); // CTRL+C
input = __ScalpiBitsU32_toggle__(input, ENABLE_MOUSE_INPUT, false);
input = __ScalpiBitsU32_toggle__(input, ENABLE_QUICK_EDIT_MODE, true); // enable mouse select and copy
input = __ScalpiBitsU32_toggle__(input, ENABLE_WINDOW_INPUT, false); // reported of change size of the console screen buffer
input = __ScalpiBitsU32_toggle__(input, ENABLE_INSERT_MODE, true); // When enabled, text entered in a console window will be inserted at the current cursor location and all text following that location will not be overwritten. When disabled, all following text will be overwritten.
t->input_mode = input;
uint32_t output = t->output_mode;
output = __ScalpiBitsU32_toggle__(output, ENABLE_LVB_GRID_WORLDWIDE, true); // enable colors
output = __ScalpiBitsU32_toggle__(output, ENABLE_VIRTUAL_TERMINAL_PROCESSING, true); // emulate VT100
output = __ScalpiBitsU32_toggle__(output, ENABLE_PROCESSED_OUTPUT, true); // Backspace, tab, bell, carriage return, and line feed characters are processed
output = __ScalpiBitsU32_toggle__(output, ENABLE_WRAP_AT_EOL_OUTPUT, false); // disable line wrap
output = __ScalpiBitsU32_toggle__(output, DISABLE_NEWLINE_AUTO_RETURN, true);
t->output_mode = output;
#elif __target_os__ == __TargetOs_linux__
// clear c_cc
cc_t* cc = &t->termios.c_cc[0]; // cc_t c_cc[NCCS]
for (int i = 0; i < NCCS ; i++) {
cc[i] = 0;
}
// timers off
cc = &t->termios.c_cc[0];
cc[VTIME] = 0;
cc[VMIN] = 1;
uint32_t cflag = t->termios.c_cflag;
cflag = __ScalpiBitsU32_toggle__(cflag, CS8, true); // use 8 bit
cflag = __ScalpiBitsU32_toggle__(cflag, CSTOPB, false); // two stops bits
cflag = __ScalpiBitsU32_toggle__(cflag, PARENB, false); // parity check
cflag = __ScalpiBitsU32_toggle__(cflag, PARODD, false); // parity check
t->termios.c_cflag = cflag;
uint32_t lflag = t->termios.c_lflag;
lflag = __ScalpiBitsU32_toggle__(lflag, ISIG, false); // disable react to Ctrl+C
lflag = __ScalpiBitsU32_toggle__(lflag, ICANON, false); // no wait '\n'
lflag = __ScalpiBitsU32_toggle__(lflag, ECHO, false); // print pressed keys
lflag = __ScalpiBitsU32_toggle__(lflag, ECHOE, false); // mashing
lflag = __ScalpiBitsU32_toggle__(lflag, ECHONL, false); // print NL
lflag = __ScalpiBitsU32_toggle__(lflag, ECHOK, false); // nl after clear line
lflag = __ScalpiBitsU32_toggle__(lflag, ECHOKE, false); // print NL after BS
lflag = __ScalpiBitsU32_toggle__(lflag, ECHOPRT, false); // print BS (BS SP BS)
lflag = __ScalpiBitsU32_toggle__(lflag, IEXTEN, false); // special funcs
t->termios.c_lflag = lflag;
uint32_t iflag = t->termios.c_iflag;
iflag = __ScalpiBitsU32_toggle__(iflag, IGNBRK, true); // ignore break control
iflag = __ScalpiBitsU32_toggle__(iflag, BRKINT, true); // do not delete all data after break control
iflag = __ScalpiBitsU32_toggle__(iflag, IXON, false); // disable react to Ctrl+S Ctlr+Q
iflag = __ScalpiBitsU32_toggle__(iflag, ISTRIP, false); // strip
iflag = __ScalpiBitsU32_toggle__(iflag, INLCR, false); // convert NL to CR
iflag = __ScalpiBitsU32_toggle__(iflag, ICRNL, false); // convert CR to NL
iflag = __ScalpiBitsU32_toggle__(iflag, XCASE, false); // convert register to UP
iflag = __ScalpiBitsU32_toggle__(iflag, IUCLC, false); // convert register to down
iflag = __ScalpiBitsU32_toggle__(iflag, IGNPAR, true); // ignore framing or parity errors
iflag = __ScalpiBitsU32_toggle__(iflag, IMAXBEL, false); // no bell
t->termios.c_iflag = iflag;
uint32_t oflag = t->termios.c_oflag;
oflag = __ScalpiBitsU32_toggle__(oflag, ONOCR, false); // on start line // Auto CR
oflag = __ScalpiBitsU32_toggle__(oflag, ONLRET, false); // on end line // Auto CR
oflag = __ScalpiBitsU32_toggle__(oflag, OPOST, true); // \_(O_o)_/
oflag = __ScalpiBitsU32_toggle__(oflag, ONLCR, true); // NL to CR
oflag = __ScalpiBitsU32_toggle__(oflag, OCRNL, false); // CR to NL
oflag = __ScalpiBitsU32_toggle__(oflag, OLCUC, false); // convert to CAPS
oflag = __ScalpiBitsU32_toggle__(oflag, XTABS, false); // convert tab
oflag = __ScalpiBitsU32_toggle__(oflag, TAB3, false); // convert tab
oflag = __ScalpiBitsU32_toggle__(oflag, OFDEL, false); // use null for deleted symbol
t->termios.c_oflag = oflag;
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
bool __OsConsoleFlags_apply__(
struct __OsConsoleFlags__ *t,
struct Os_Console_Input *input,
struct __OsConsoleOutput__ *output
) {
// expected inited
bool ok = true;
#if __target_os__ == __TargetOs_windows__
int result1 = SetConsoleMode(input->handle, t->input_mode);
if (result1 == 0) {
ok = false;
// todo GetLastError();
}
int result2 = SetConsoleMode(output->__OsConsoleOutput_handle__, t->output_mode);
if (result2 == 0) {
ok = false;
// todo GetLastError();
}
#elif __target_os__ == __TargetOs_linux__
tcsetattr(input->fileno, TCSANOW, &t->termios);
tcsetattr(output->__OsConsoleOutput_fileno__, TCSANOW, &t->termios);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
bool __OsConsoleFlags_init__(struct __OsConsoleFlags__ *t, struct Os_Console_Input* input, struct __OsConsoleOutput__ *output) {
bool ok = true;
#if __target_os__ == __TargetOs_windows__
bool result1 = GetConsoleMode(input->handle, &t->input_mode);
if (result1 != 0) {
bool result2 = GetConsoleMode(output->__OsConsoleOutput_handle__, &t->output_mode);
if (result2 != 0) {
t->inited = true;
} else {
ok = false;
}
} else {
ok = false;
}
#elif __target_os__ == __TargetOs_linux__
int result = tcgetattr(input->fileno, &t->termios);
if (result == 0) {
t->inited = true;
} else {
ok = false;
}
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return ok;
}
size_t __OsFallbackConsole_write__(void* unused_ctx, char* data, size_t len) {
#if __target_os__ == __TargetOs_windows__
struct __OsConsoleOutput__ console_output;
__OsConsoleOutput_init__(&console_output, GetStdHandle(STD_OUTPUT_HANDLE));
__OsConsoleOutput_write__(&console_output, data, len);
#elif __target_os__ == __TargetOs_linux__
struct __OsConsoleOutput__ console_output;
__OsConsoleOutput_init__ (&console_output, stdout);
__OsConsoleOutput_write__ (&console_output, data, len);
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
return len;
}
// Helper
bool App_Os_Helper_init(struct __OsHelper__* os_helper) {
#if __target_os__ == __TargetOs_windows__
os_helper->instance = GetModuleHandleA(0);
if (os_helper->instance) { // enable network
return true;
}
FreeLibrary(os_helper->instance);
return false;
#elif __target_os__ == __TargetOs_linux__
return true; // nothing todo.
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
void App_Os_Helper_deinit(struct __OsHelper__* os_helper) {
#if __target_os__ == __TargetOs_windows__
FreeLibrary(os_helper->instance);
#elif __target_os__ == __TargetOs_linux__
// TODO ME FOR LINUX
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
void App_Os_Helper_process(struct __OsHelper__* os_helper) {
#if __target_os__ == __TargetOs_windows__
MSG msg;
size_t message_count = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
if (message_count == 0) return;
TranslateMessage(&msg);
DispatchMessageA(&msg);
#elif __target_os__ == __TargetOs_linux__
// TODO ME FOR LINUX
#else
#error "not implemented current __target_os__ or not defined. (expected __TargetOs_ value)"
#endif
}
// Scalpi
// Scalpi_Logger
void Scalpi_Logger_init (struct Scalpi_Logger* t) {
for (int i = 0; i < ARRAY_LEN(t->writers); i++) {
struct __Scalpi_Writer__* w = &t->writers[i];
w->context = 0;
w->write = 0;
}
}
size_t Scalpi_Logger_writeToSelf(struct Scalpi_Logger* t, const char bytes[], size_t len) {
for (size_t i = 0; i < ARRAY_LEN(t->writers); i++) {
struct __Scalpi_Writer__* w = &t->writers[i];
if (w->write) {
size_t writed = w->write(w->context, bytes, len);
}
}
}
// __ScalpiTerminalOutput_CursorPos__
void __ScalpiTerminalOutputCursorPos_init__(__ScalpiTerminalOutput_CursorPos__ *cursor_pos) {
cursor_pos->x = 0;
cursor_pos->y = 0;
}
// App
// struct App
bool App_init(struct App* t) {
Scalpi_Logger_init(&t->logger); // preinit console output for debug
if (App_Os_Helper_init(&t->__App_osHelper__)) {
t->tick = __os_getTick__();
return true;
// fallback
// App_Os_Helper_deinit(&t->__App_osHelper__);
} else {
printf("%d app.os_helper not inited\r\n", __LINE__);
}
return false;
}
void App_deinit(struct App* app) {
App_Os_Helper_deinit(&app->__App_osHelper__);
}
bool App_process(struct App* t) {
App_Os_Helper_process(&t->__App_osHelper__);
return true;
}
void App_waitToNextFrame(struct App* t) {
uint64_t expected_frame_end_time = t->tick + App_delay_to_start_frame_target;
uint64_t resulting_frame_end_time = __os_getTick__();
if (resulting_frame_end_time > expected_frame_end_time + 120) {
uint64_t delta = resulting_frame_end_time - expected_frame_end_time;
printf("%d \t hitch detection: %zu delta: %zu ms \r\n", __LINE__, t->tick, delta);
}
uint64_t delay_sleep = 1;
if (resulting_frame_end_time < expected_frame_end_time) {
delay_sleep = expected_frame_end_time - resulting_frame_end_time;
}
Os_sleep(delay_sleep);
t->tick = resulting_frame_end_time + delay_sleep;
}
// main
bool tests() {
if ( true
and cpu_checkNumberFormat()
// and etc...
// and etc...
) {
return true;
} else {
printf("%d fail tests \r\n", __LINE__);
return false;
}
return true;
}
bool real_main(int args_len, char** args_ptr) {
if (tests()) {
if (App_init(&global_app)) {
while(true) {
if (!App_process(&global_app)) break;
App_waitToNextFrame(&global_app);
}
App_deinit(&global_app);
return true;
} else {
printf("%d fail: App_init\r\n", __LINE__);
}
} else {
printf("%d fail tests \r\n", __LINE__);
}
return false;
}
int main2(int args_len, char** args_ptr) {
if (real_main(args_len, args_ptr)) return 0;
return 1;
}