#ifndef RAY_TERM_H
#define RAY_TERM_H
#include <rayforce.h>
#if defined(RAY_OS_WINDOWS)
#include <windows.h>
#define KEYCODE_RETURN '\r'
#else
#include <termios.h>
#define KEYCODE_RETURN '\n'
#endif
#define KEYCODE_BACKSPACE '\b'
#define KEYCODE_DELETE 0x7f
#define KEYCODE_TAB '\t'
#define KEYCODE_UP 'A'
#define KEYCODE_DOWN 'B'
#define KEYCODE_LEFT 'D'
#define KEYCODE_RIGHT 'C'
#define KEYCODE_HOME 'H'
#define KEYCODE_END 'F'
#define KEYCODE_ESCAPE 0x1b
#define KEYCODE_CTRL_A 0x01
#define KEYCODE_CTRL_B 0x02
#define KEYCODE_CTRL_C 0x03
#define KEYCODE_CTRL_D 0x04
#define KEYCODE_CTRL_E 0x05
#define KEYCODE_CTRL_F 0x06
#define KEYCODE_CTRL_K 0x0b
#define KEYCODE_CTRL_N 0x0e
#define KEYCODE_CTRL_P 0x10
#define KEYCODE_CTRL_R 0x12
#define KEYCODE_CTRL_U 0x15
#define KEYCODE_CTRL_W 0x17
#define TERM_BUF_SIZE 4096
#define HIST_DEFAULT_CAP 256
typedef struct ray_hist {
char** entries;
int32_t count;
int32_t capacity;
int32_t index;
int32_t curr_saved;
char curr[TERM_BUF_SIZE];
int32_t curr_len;
} ray_hist_t;
typedef struct ray_term {
ray_t* _block;
#if defined(RAY_OS_WINDOWS)
HANDLE h_stdin;
HANDLE h_stdout;
DWORD old_stdin_mode;
DWORD old_stdout_mode;
#else
struct termios oldattr;
struct termios newattr;
#endif
int32_t input_len;
char input[8];
int32_t buf_len;
int32_t buf_pos;
char buf[TERM_BUF_SIZE];
int32_t term_width;
int32_t term_height;
int32_t prompt_len;
char prompt_prefix[80];
int32_t prompt_prefix_len;
int32_t prompt_prefix_vis;
int32_t last_total_rows;
int32_t last_cursor_row;
ray_hist_t hist;
int32_t search_mode;
char search_buf[256];
int32_t search_len;
int32_t search_match_idx;
char ghost[TERM_BUF_SIZE];
int32_t ghost_len;
int32_t ghost_word_start;
int32_t ghost_word_len;
const char* comp_items[256];
int32_t comp_count;
int32_t comp_cycling;
int32_t comp_cycle_idx;
int32_t comp_cycle_start;
int32_t comp_cycle_len;
char comp_scratch[TERM_BUF_SIZE];
int32_t comp_scratch_len;
char multiline_buf[TERM_BUF_SIZE];
int32_t multiline_len;
int32_t esc_state;
int32_t esc_buf_len;
} ray_term_t;
ray_term_t* ray_term_create(void);
void ray_term_destroy(ray_term_t* term);
int64_t ray_term_getc(ray_term_t* term);
void ray_term_get_size(ray_term_t* term);
void ray_cursor_move_start(void);
void ray_cursor_move_left(int32_t n);
void ray_cursor_move_right(int32_t n);
void ray_cursor_move_up(int32_t n);
void ray_cursor_move_down(int32_t n);
void ray_line_clear(void);
void ray_line_clear_below(void);
void ray_cursor_hide(void);
void ray_cursor_show(void);
int32_t ray_term_visual_width(const char* str, int32_t len);
void ray_term_goto_position(ray_term_t* term, int32_t from_pos, int32_t to_pos);
ray_t* ray_term_read(ray_term_t* term);
void ray_term_redraw(ray_term_t* term);
void ray_term_prompt(ray_term_t* term);
void ray_term_set_prompt_prefix(ray_term_t* term, const char* prefix);
#define RAY_TERM_EOF ((ray_t*)(uintptr_t)1)
void ray_term_begin(ray_term_t* term);
ray_t* ray_term_feed(ray_term_t* term);
void ray_hist_create(ray_hist_t* hist);
void ray_hist_destroy(ray_hist_t* hist);
void ray_hist_add(ray_hist_t* hist, const char* buf, int32_t len);
int32_t ray_hist_prev(ray_hist_t* hist, char* buf, int32_t buf_len);
int32_t ray_hist_next(ray_hist_t* hist, char* buf);
void ray_hist_load(ray_hist_t* hist, const char* path);
void ray_hist_save(ray_hist_t* hist, const char* path);
int32_t ray_hist_search(ray_hist_t* hist, const char* needle, int32_t needle_len,
int32_t start_idx);
int32_t ray_term_find_matching_paren(const char* buf, int32_t buf_len,
int32_t cursor_pos);
void ray_term_collect_completions(ray_term_t* term, const char* prefix,
int32_t prefix_len);
int32_t ray_term_count_unmatched(ray_term_t* term);
void ray_term_continuation_prompt(ray_term_t* term);
void ray_term_install_signals(ray_term_t* term);
int ray_term_interrupted(void);
void ray_term_clear_interrupt(void);
void ray_term_eval_begin(ray_term_t* term);
void ray_term_eval_end(ray_term_t* term);
#define HIST_MAX_ENTRIES 1000
#define HIST_DEFAULT_PATH ".rayforce_history"
#endif