aboutsummaryrefslogblamecommitdiffstats
path: root/libterminput.h
blob: d5c54394bb4a2ce4f2071ae479e1ac7f023a261a (plain) (tree)
1
2
3
4
5
6
7
8
9
10






                                                         


                                                         
                                                     


                                     




                                                       



                                                            
                                                          


                                                             


                                                       

  











                                  


                                                                                  











                         
                                        
                         

                                          




                                           

                           









                              
                                 
                                  


                                     

                                  
                                  

  














                                                                                               

                          


                                           
                          



                                                                  







                                      









                                                                                                      





                                    












                                                                                                                            
                              
                                    

                 

  

                                    


                                                                                                
                                                                                                     








                                                                           
                                      
                             
                            

                  


                           
                      

                        
                         












                                                                                               


                                                                                      
                                                               





                                                                              


                                                                                            

      
/* See LICENSE file for copyright and license details. */
#ifndef LIBTERMINPUT_H
#define LIBTERMINPUT_H

#include <stddef.h>


/**
 * Flags for supporting incompatible input; the user must
 * set or clear his flag after setting or clearing it on
 * the terminal, and the user must make sure that the
 * terminal support this flag if set.
 */
enum libterminput_flags {
	LIBTERMINPUT_DECSET_1005              = 0x0001,
	LIBTERMINPUT_MACRO_ON_CSI_M           = 0x0002,
	LIBTERMINPUT_PAUSE_ON_CSI_P           = 0x0004,
	LIBTERMINPUT_INS_ON_CSI_AT            = 0x0008,
	LIBTERMINPUT_SEPARATE_BACKTAB         = 0x0010,

	/**
	 * If an ESC is received without anything after it,
	 * return ESC keypress. This is not always desirable
	 * behaviour as the user may manually press ESC to
	 * simulate a keypress that terminal does not support
	 * (yes, this is a real world issue).
	 */
	LIBTERMINPUT_ESC_ON_BLOCK             = 0x0020,

	LIBTERMINPUT_AWAITING_CURSOR_POSITION = 0x0040
};

enum libterminput_mod {
	LIBTERMINPUT_SHIFT = 0x01,
	LIBTERMINPUT_META  = 0x02,
	LIBTERMINPUT_CTRL  = 0x04
};

enum libterminput_key {
	LIBTERMINPUT_SYMBOL,
	LIBTERMINPUT_UP,
	LIBTERMINPUT_DOWN,
	LIBTERMINPUT_RIGHT,
	LIBTERMINPUT_LEFT,
	LIBTERMINPUT_BEGIN,   /* keypad 5 without numlock */
	LIBTERMINPUT_TAB,     /* backtab is interpreted as shift+tab by default */
	LIBTERMINPUT_BACKTAB, /* requires LIBTERMINPUT_SEPARATE_BACKTAB */
	LIBTERMINPUT_F1,
	LIBTERMINPUT_F2,
	LIBTERMINPUT_F3,
	LIBTERMINPUT_F4,
	LIBTERMINPUT_F5,
	LIBTERMINPUT_F6,
	LIBTERMINPUT_F7,
	LIBTERMINPUT_F8,
	LIBTERMINPUT_F9,
	LIBTERMINPUT_F10,
	LIBTERMINPUT_F11,
	LIBTERMINPUT_F12,
	LIBTERMINPUT_HOME,  /* = find */
	LIBTERMINPUT_INS,
	LIBTERMINPUT_DEL,   /* = remove */
	LIBTERMINPUT_END,   /* = select */
	LIBTERMINPUT_PRIOR, /* page up   */
	LIBTERMINPUT_NEXT,  /* page down */
	LIBTERMINPUT_ERASE, /* backspace */
	LIBTERMINPUT_ENTER, /* return    */
	LIBTERMINPUT_ESC,
	LIBTERMINPUT_MACRO,
	LIBTERMINPUT_PAUSE,
	LIBTERMINPUT_KEYPAD_0,
	LIBTERMINPUT_KEYPAD_1,
	LIBTERMINPUT_KEYPAD_2,
	LIBTERMINPUT_KEYPAD_3,
	LIBTERMINPUT_KEYPAD_4,
	LIBTERMINPUT_KEYPAD_5,
	LIBTERMINPUT_KEYPAD_6,
	LIBTERMINPUT_KEYPAD_7,
	LIBTERMINPUT_KEYPAD_8,
	LIBTERMINPUT_KEYPAD_9,
	LIBTERMINPUT_KEYPAD_PLUS,
	LIBTERMINPUT_KEYPAD_MINUS,
	LIBTERMINPUT_KEYPAD_TIMES,
	LIBTERMINPUT_KEYPAD_DIVISION,
	LIBTERMINPUT_KEYPAD_DECIMAL,
	LIBTERMINPUT_KEYPAD_COMMA,
	LIBTERMINPUT_KEYPAD_POINT,
	LIBTERMINPUT_KEYPAD_ENTER,
};

enum libterminput_button {
	LIBTERMINPUT_NO_BUTTON,
	LIBTERMINPUT_BUTTON1,      /* left (assuming right-handed) */
	LIBTERMINPUT_BUTTON2,      /* middle */
	LIBTERMINPUT_BUTTON3,      /* right (assuming right-handed) */
	LIBTERMINPUT_SCROLL_UP,    /* no corresponding release event shall be generated */
	LIBTERMINPUT_SCROLL_DOWN,  /* no corresponding release event shall be generated */
	LIBTERMINPUT_SCROLL_LEFT,  /* may or may not have a corresponding release event */
	LIBTERMINPUT_SCROLL_RIGHT, /* may or may not have a corresponding release event */
	LIBTERMINPUT_XBUTTON1,     /* extended button 1, also known as backward */
	LIBTERMINPUT_XBUTTON2,     /* extended button 2, also known as forward */
	LIBTERMINPUT_XBUTTON3,     /* extended button 3, you probably don't have this button */
	LIBTERMINPUT_XBUTTON4      /* extended button 4, you probably don't have this button */
};

enum libterminput_type {
	LIBTERMINPUT_NONE,
	LIBTERMINPUT_KEYPRESS,
	LIBTERMINPUT_BRACKETED_PASTE_START,
	LIBTERMINPUT_BRACKETED_PASTE_END,
	LIBTERMINPUT_TEXT,
	LIBTERMINPUT_MOUSEEVENT,
	LIBTERMINPUT_TERMINAL_IS_OK,     /* response to CSI 5 n */
	LIBTERMINPUT_TERMINAL_IS_NOT_OK, /* response to CSI 5 n */
	LIBTERMINPUT_CURSOR_POSITION     /* response to CSI 6 n */
};

enum libterminput_event {
	LIBTERMINPUT_PRESS,
	LIBTERMINPUT_RELEASE,
	LIBTERMINPUT_MOTION,
	LIBTERMINPUT_HIGHLIGHT_INSIDE,
	LIBTERMINPUT_HIGHLIGHT_OUTSIDE
};

struct libterminput_keypress {
	enum libterminput_type type;
	enum libterminput_key key;
	unsigned long long int times; /* if .times > 1, next will be the same, but will .times -= 1 */
	enum libterminput_mod mods;
	char symbol[7];               /* use if .key == LIBTERMINPUT_SYMBOL */
};

struct libterminput_text {
	enum libterminput_type type;
	size_t nbytes;
	char bytes[512];
};

struct libterminput_mouseevent {
	enum libterminput_type type;
	enum libterminput_mod mods;      /* Set to 0 for LIBTERMINPUT_HIGHLIGHT_INSIDE and LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
	enum libterminput_button button; /* Set to 1 for LIBTERMINPUT_HIGHLIGHT_INSIDE and LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
	enum libterminput_event event;
	size_t x;
	size_t y;
	size_t start_x; /* Only set for LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
	size_t start_y; /* Only set for LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
	size_t end_x;   /* Only set for LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
	size_t end_y;   /* Only set for LIBTERMINPUT_HIGHLIGHT_OUTSIDE */
};

struct libterminput_position {
	enum libterminput_type type;
	size_t x;
	size_t y;
};

union libterminput_input {
	enum libterminput_type type;
	struct libterminput_keypress keypress;     /* use if .type == LIBTERMINPUT_KEYPRESS */
	struct libterminput_text text;             /* use if .type == LIBTERMINPUT_TEXT */
	struct libterminput_mouseevent mouseevent; /* use if .type == LIBTERMINPUT_MOUSEEVENT */
	struct libterminput_position position;     /* use if .type == LIBTERMINPUT_CURSOR_POSITION */
};


/**
 * This struct should be considered opaque
 */
struct libterminput_state {
	int inited; /* whether the input in initialised, not this struct */
	enum libterminput_mod mods;
	enum libterminput_flags flags;
	char bracketed_paste;
	char mouse_tracking;
	char meta;
	char n;
	size_t stored_head;
	size_t stored_tail;
	char paused;
	char npartial;
	char partial[7];
	char key[44];
	char stored[512];
};


/**
 * Get input from the terminal
 * 
 * @param   fd     The file descriptor to the terminal
 * @param   input  Output parameter for input
 * @param   ctx    State for the terminal, parts of the state may be stored in `input`
 * @return         1 normally, 0 on end of input, -1 on error
 */
int libterminput_read(int fd, union libterminput_input *input, struct libterminput_state *ctx);

inline int
libterminput_is_ready(union libterminput_input *input, struct libterminput_state *ctx)
{
	if (!ctx->inited || ctx->paused || ctx->mouse_tracking)
		return 0;
	if (input->type == LIBTERMINPUT_KEYPRESS && input->keypress.times > 1)
		return 1;
	return ctx->stored_head > ctx->stored_tail;
}

int libterminput_set_flags(struct libterminput_state *ctx, enum libterminput_flags flags);
int libterminput_clear_flags(struct libterminput_state *ctx, enum libterminput_flags flags);


#endif