1 #ifndef __MLE_H
2 #define __MLE_H
3 
4 #include <stdint.h>
5 #include <limits.h>
6 #include <termbox.h>
7 #include <uthash.h>
8 #include <lua53/lua.h>
9 #include <lua53/lualib.h>
10 #include <lua53/lauxlib.h>
11 #include "mlbuf.h"
12 
13 // Typedefs
14 typedef struct editor_s editor_t; // A container for editor-wide globals
15 typedef struct bview_s bview_t; // A view of a buffer
16 typedef struct bview_rect_s bview_rect_t; // A rectangle in bview with a default styling
17 typedef struct bview_listener_s bview_listener_t; // A listener to buffer events in a bview
18 typedef void (*bview_listener_cb_t)(bview_t *bview, baction_t *action, void *udata); // A bview_listener_t callback
19 typedef struct cursor_s cursor_t; // A cursor (insertion mark + selection bound mark) in a buffer
20 typedef struct loop_context_s loop_context_t; // Context for a single _editor_loop
21 typedef struct cmd_s cmd_t; // A command definition
22 typedef struct cmd_context_s cmd_context_t; // Context for a single command invocation
23 typedef struct observer_s observer_t; // An observer of a cmd or event
24 typedef struct kinput_s kinput_t; // A single key input (similar to a tb_event from termbox)
25 typedef struct kmacro_s kmacro_t; // A sequence of kinputs and a name
26 typedef struct kmap_s kmap_t; // A map of keychords to functions
27 typedef struct kmap_node_s kmap_node_t; // A node in a list of keymaps
28 typedef struct kbinding_def_s kbinding_def_t; // A definition of a keymap
29 typedef struct kbinding_s kbinding_t; // A single binding in a keymap
30 typedef struct syntax_s syntax_t; // A syntax definition
31 typedef struct syntax_node_s syntax_node_t; // A node in a linked list of syntaxes
32 typedef struct srule_def_s srule_def_t; // A definition of a syntax
33 typedef struct aproc_s aproc_t; // An asynchronous process
34 typedef void (*aproc_cb_t)(aproc_t *self, char *buf, size_t buf_len); // An aproc_t callback
35 typedef struct editor_prompt_params_s editor_prompt_params_t; // Extra params for editor_prompt
36 typedef struct tb_event tb_event_t; // A termbox event
37 typedef struct prompt_history_s prompt_history_t; // A map of prompt histories keyed by prompt_str
38 typedef struct prompt_hnode_s prompt_hnode_t; // A node in a linked list of prompt history
39 typedef int (*cmd_func_t)(cmd_context_t *ctx); // A command function
40 typedef int (*observer_func_t)(char *event_name, void *event_data, void *udata); // An event callback function
41 typedef struct uscript_s uscript_t; // A userscript
42 typedef struct uhandle_s uhandle_t; // A method handle in a uscript
43 
44 // kinput_t
45 struct kinput_s {
46     uint8_t mod;
47     uint32_t ch;
48     uint16_t key;
49 };
50 
51 // bview_rect_t
52 struct bview_rect_s {
53     int x;
54     int y;
55     int w;
56     int h;
57     uint16_t fg;
58     uint16_t bg;
59 };
60 
61 // editor_t
62 struct editor_s {
63     int w;
64     int h;
65     bview_t *top_bviews;
66     bview_t *all_bviews;
67     bview_t *active;
68     bview_t *active_edit;
69     bview_t *active_edit_root;
70     bview_t *status;
71     bview_t *prompt;
72     bview_rect_t rect_edit;
73     bview_rect_t rect_status;
74     bview_rect_t rect_prompt;
75     syntax_t *syntax_map;
76     int is_display_disabled;
77     kmacro_t *macro_map;
78     kinput_t macro_toggle_key;
79     kmacro_t *macro_record;
80     kmacro_t *macro_apply;
81     size_t macro_apply_input_index;
82     int is_recording_macro;
83     char *startup_macro_name;
84     cmd_t *cmd_map;
85     kmap_t *kmap_map;
86     kmap_t *kmap_normal;
87     kmap_t *kmap_prompt_input;
88     kmap_t *kmap_prompt_yn;
89     kmap_t *kmap_prompt_yna;
90     kmap_t *kmap_prompt_ok;
91     kmap_t *kmap_prompt_isearch;
92     kmap_t *kmap_prompt_menu;
93     kmap_t *kmap_menu;
94     prompt_history_t *prompt_history;
95     char *kmap_init_name;
96     kmap_t *kmap_init;
97     aproc_t *aprocs;
98     uscript_t *uscripts;
99     observer_t *observers;
100     FILE *tty;
101     int ttyfd;
102     char *syntax_override;
103     int linenum_type;
104     int tab_width;
105     int tab_to_space;
106     int trim_paste;
107     int auto_indent;
108     int read_rc_file;
109     int highlight_bracket_pairs;
110     int color_col;
111     int soft_wrap;
112     int viewport_scope_x; // TODO cli option
113     int viewport_scope_y; // TODO cli option
114     int headless_mode;
115     loop_context_t *loop_ctx;
116     int loop_depth;
117     int is_in_init;
118     char *insertbuf;
119     size_t insertbuf_size;
120     char *cut_buffer;
121     #define MLE_ERRSTR_SIZE 256
122     char errstr[MLE_ERRSTR_SIZE];
123     char infostr[MLE_ERRSTR_SIZE];
124     int debug_exit_after_startup;
125     int debug_dump_state_on_exit;
126     int exit_code;
127 };
128 
129 // srule_def_t
130 struct srule_def_s {
131     char *re;
132     char *re_end;
133     uint16_t fg;
134     uint16_t bg;
135 };
136 
137 // syntax_node_t
138 struct syntax_node_s {
139     srule_t *srule;
140     syntax_node_t *next;
141     syntax_node_t *prev;
142 };
143 
144 // syntax_t
145 struct syntax_s {
146     char *name;
147     char *path_pattern;
148     int tab_width;
149     int tab_to_space;
150     srule_node_t *srules;
151     UT_hash_handle hh;
152 };
153 
154 // bview_t
155 struct bview_s {
156     #define MLE_BVIEW_TYPE_EDIT 0
157     #define MLE_BVIEW_TYPE_STATUS 1
158     #define MLE_BVIEW_TYPE_PROMPT 2
159     editor_t *editor;
160     int x;
161     int y;
162     int w;
163     int h;
164     int is_resized;
165     int type;
166     int linenum_width;
167     int abs_linenum_width;
168     int rel_linenum_width;
169     bview_rect_t rect_caption;
170     bview_rect_t rect_lines;
171     bview_rect_t rect_margin_left;
172     bview_rect_t rect_buffer;
173     bview_rect_t rect_margin_right;
174     buffer_t *buffer;
175     bint_t viewport_x;
176     bint_t viewport_x_vcol;
177     bint_t viewport_y;
178     bline_t *viewport_bline;
179     int viewport_scope_x;
180     int viewport_scope_y;
181     bview_t *split_parent;
182     bview_t *split_child;
183     float split_factor;
184     int split_is_vertical;
185     char *prompt_str;
186     char *path;
187     bint_t startup_linenum;
188     kmap_node_t *kmap_stack;
189     kmap_node_t *kmap_tail;
190     cursor_t *cursors;
191     cursor_t *active_cursor;
192     char *last_search;
193     srule_t *isearch_rule;
194     int tab_width;
195     int tab_to_space;
196     syntax_t *syntax;
197     aproc_t *aproc;
198     cmd_func_t menu_callback;
199     int is_menu;
200     #ifndef PATH_MAX
201     #define PATH_MAX 4096
202     #endif
203     char init_cwd[PATH_MAX + 1];
204     bview_listener_t *listeners;
205     bview_t *top_next;
206     bview_t *top_prev;
207     bview_t *all_next;
208     bview_t *all_prev;
209 };
210 
211 // bview_listener_t
212 struct bview_listener_s {
213     bview_listener_cb_t callback;
214     void *udata;
215     bview_listener_t *next;
216     bview_listener_t *prev;
217 };
218 
219 // cursor_t
220 struct cursor_s {
221     bview_t *bview;
222     mark_t *mark;
223     mark_t *anchor;
224     int is_anchored;
225     int is_asleep;
226     srule_t *sel_rule;
227     char *cut_buffer;
228     cursor_t *next;
229     cursor_t *prev;
230 };
231 
232 // kmacro_t
233 struct kmacro_s {
234     char *name;
235     kinput_t *inputs;
236     size_t inputs_len;
237     size_t inputs_cap;
238     UT_hash_handle hh;
239 };
240 
241 // cmd_t
242 struct cmd_s {
243     char *name;
244     cmd_func_t func;
245     void *udata;
246     int is_resolved;
247     UT_hash_handle hh;
248 };
249 
250 // kbinding_def_t
251 struct kbinding_def_s {
252     #define MLE_KBINDING_DEF(pcmdname, pkeypatt)             { (pcmdname), (pkeypatt), NULL }
253     #define MLE_KBINDING_DEF_EX(pcmdname, pkeypatt, pstatp)  { (pcmdname), (pkeypatt), (pstatp) }
254     char *cmd_name;
255     char *key_patt;
256     char *static_param;
257 };
258 
259 // kbinding_t
260 struct kbinding_s {
261     kinput_t input;
262     char *cmd_name;
263     cmd_t *cmd;
264     char *static_param;
265     char *key_patt;
266     int is_leaf;
267     kbinding_t *children;
268     UT_hash_handle hh;
269 };
270 
271 // kmap_node_t
272 struct kmap_node_s {
273     kmap_t *kmap;
274     bview_t *bview;
275     kmap_node_t *next;
276     kmap_node_t *prev;
277 };
278 
279 // kmap_t
280 struct kmap_s {
281     char *name;
282     kbinding_t *bindings;
283     int allow_fallthru;
284     char *default_cmd_name;
285     cmd_t *default_cmd;
286     UT_hash_handle hh;
287 };
288 
289 // cmd_context_t
290 struct cmd_context_s {
291     #define MLE_PASTEBUF_INCR 1024
292     editor_t *editor;
293     loop_context_t *loop_ctx;
294     cmd_t *cmd;
295     buffer_t *buffer;
296     bview_t *bview;
297     cursor_t *cursor;
298     kinput_t input;
299     char *static_param;
300     int is_user_input;
301     kinput_t *pastebuf;
302     size_t pastebuf_len;
303     size_t pastebuf_size;
304     int has_pastebuf_leftover;
305     kinput_t pastebuf_leftover;
306 };
307 
308 // observer_t
309 struct observer_s {
310     char *event_name;
311     observer_func_t callback;
312     void *udata;
313     observer_t *next;
314     observer_t *prev;
315 };
316 
317 // loop_context_t
318 struct loop_context_s {
319     #define MLE_LOOP_CTX_MAX_NUMERIC_LEN 20
320     #define MLE_LOOP_CTX_MAX_NUMERIC_PARAMS 8
321     #define MLE_LOOP_CTX_MAX_WILDCARD_PARAMS 8
322     #define MLE_LOOP_CTX_MAX_COMPLETE_TERM_SIZE 256
323     bview_t *invoker;
324     char numeric[MLE_LOOP_CTX_MAX_NUMERIC_LEN + 1];
325     kbinding_t *numeric_node;
326     int numeric_len;
327     uintmax_t numeric_params[MLE_LOOP_CTX_MAX_NUMERIC_PARAMS];
328     int numeric_params_len;
329     uint32_t wildcard_params[MLE_LOOP_CTX_MAX_WILDCARD_PARAMS];
330     int wildcard_params_len;
331     kbinding_t *binding_node;
332     int need_more_input;
333     int should_exit;
334     char *prompt_answer;
335     cmd_func_t prompt_callack;
336     prompt_hnode_t *prompt_hnode;
337     int tab_complete_index;
338     char tab_complete_term[MLE_LOOP_CTX_MAX_COMPLETE_TERM_SIZE];
339     cmd_t *last_cmd;
340     str_t last_insert;
341 };
342 
343 // aproc_t
344 struct aproc_s {
345     editor_t *editor;
346     void *owner;
347     aproc_t **owner_aproc;
348     FILE *rpipe;
349     FILE *wpipe;
350     pid_t pid;
351     int rfd;
352     int wfd;
353     int is_done;
354     aproc_cb_t callback;
355     aproc_t *next;
356     aproc_t *prev;
357 };
358 
359 // editor_prompt_params_t
360 struct editor_prompt_params_s {
361     char *data;
362     int data_len;
363     kmap_t *kmap;
364     bview_listener_cb_t prompt_cb;
365     void *prompt_cb_udata;
366 };
367 
368 // prompt_history_t
369 struct prompt_history_s {
370     char *prompt_str;
371     prompt_hnode_t *prompt_hlist;
372     UT_hash_handle hh;
373 };
374 
375 // prompt_hnode_t
376 struct prompt_hnode_s {
377     char *data;
378     bint_t data_len;
379     prompt_hnode_t *prev;
380     prompt_hnode_t *next;
381 };
382 
383 // uscript_t
384 struct uscript_s {
385     editor_t *editor;
386     lua_State *L;
387     uhandle_t *uhandles;
388     uscript_t *prev;
389     uscript_t *next;
390 };
391 
392 // uhandle_t
393 struct uhandle_s {
394     uscript_t *uscript;
395     int callback_ref;
396     uhandle_t *next;
397     uhandle_t *prev;
398 };
399 
400 // editor functions
401 int editor_init(editor_t *editor, int argc, char **argv);
402 int editor_run(editor_t *editor);
403 int editor_deinit(editor_t *editor);
404 int editor_prompt(editor_t *editor, char *prompt, editor_prompt_params_t *params, char **optret_answer);
405 int editor_menu(editor_t *editor, cmd_func_t fn_callback, char *opt_buf_data, int opt_buf_data_len, aproc_t *opt_aproc, bview_t **optret_menu);
406 int editor_open_bview(editor_t *editor, bview_t *opt_parent, int type, char *opt_path, int opt_path_len, int make_active, bint_t linenum, int skip_resize, buffer_t *opt_buffer, bview_t **optret_bview);
407 int editor_close_bview(editor_t *editor, bview_t *bview, int *optret_num_closed);
408 int editor_set_active(editor_t *editor, bview_t *bview);
409 int editor_bview_edit_count(editor_t *editor);
410 int editor_count_bviews_by_buffer(editor_t *editor, buffer_t *buffer);
411 int editor_register_cmd(editor_t *editor, cmd_t *cmd);
412 int editor_register_observer(editor_t *editor, char *event_name, void *udata, observer_func_t fn_callback, observer_t **optret_observer);
413 int editor_notify_observers(editor_t *editor, char *event_name, void *event_data);
414 int editor_destroy_observer(editor_t *editor, observer_t *observer);
415 int editor_get_input(editor_t *editor, loop_context_t *loop_ctx, cmd_context_t *ctx);
416 int editor_display(editor_t *editor);
417 int editor_debug_dump(editor_t *editor, FILE *fp);
418 int editor_input_to_key(editor_t *editor, kinput_t *input, char *keybuf);
419 
420 // bview functions
421 bview_t *bview_get_split_root(bview_t *self);
422 bview_t *bview_new(editor_t *editor, char *opt_path, int opt_path_len, buffer_t *opt_buffer);
423 int bview_add_cursor_asleep(bview_t *self, bline_t *opt_bline, bint_t opt_col, cursor_t **optret_cursor);
424 int bview_add_cursor(bview_t *self, bline_t *opt_bline, bint_t opt_col, cursor_t **optret_cursor);
425 int bview_add_listener(bview_t *self, bview_listener_cb_t fn_callback, void *udata);
426 int bview_center_viewport_y(bview_t *self);
427 int bview_destroy(bview_t *self);
428 int bview_destroy_listener(bview_t *self, bview_listener_t *listener);
429 int bview_draw(bview_t *self);
430 int bview_draw_cursor(bview_t *self, int set_real_cursor);
431 int bview_get_active_cursor_count(bview_t *self);
432 int bview_get_screen_coords(bview_t *self, mark_t *mark, int *ret_x, int *ret_y, struct tb_cell **optret_cell);
433 int bview_max_viewport_y(bview_t *self);
434 int bview_open(bview_t *self, char *path, int path_len);
435 int bview_pop_kmap(bview_t *bview, kmap_t **optret_kmap);
436 int bview_push_kmap(bview_t *bview, kmap_t *kmap);
437 int bview_rectify_viewport(bview_t *self);
438 int bview_remove_cursor(bview_t *self, cursor_t *cursor);
439 int bview_remove_cursors_except(bview_t *self, cursor_t *one);
440 int bview_resize(bview_t *self, int x, int y, int w, int h);
441 int bview_set_syntax(bview_t *self, char *opt_syntax);
442 int bview_set_viewport_y(bview_t *self, bint_t y, int do_rectify);
443 int bview_split(bview_t *self, int is_vertical, float factor, bview_t **optret_bview);
444 int bview_wake_sleeping_cursors(bview_t *self);
445 int bview_zero_viewport_y(bview_t *self);
446 
447 // cursor functions
448 int cursor_clone(cursor_t *cursor, int use_srules, cursor_t **ret_clone);
449 int cursor_cut_copy(cursor_t *cursor, int is_cut, int use_srules, int append);
450 int cursor_destroy(cursor_t *cursor);
451 int cursor_drop_anchor(cursor_t *cursor, int use_srules);
452 int cursor_get_lo_hi(cursor_t *cursor, mark_t **ret_lo, mark_t **ret_hi);
453 int cursor_get_mark(cursor_t *cursor, mark_t **ret_mark);
454 int cursor_get_anchor(cursor_t *cursor, mark_t **ret_anchor);
455 int cursor_lift_anchor(cursor_t *cursor);
456 int cursor_replace(cursor_t *cursor, int interactive, char *opt_regex, char *opt_replacement);
457 int cursor_select_between(cursor_t *cursor, mark_t *a, mark_t *b, int use_srules);
458 int cursor_select_by(cursor_t *cursor, const char *strat, int use_srules);
459 int cursor_select_by_bracket(cursor_t *cursor, int use_srules);
460 int cursor_select_by_string(cursor_t *cursor, int use_srules);
461 int cursor_select_by_word_back(cursor_t *cursor, int use_srules);
462 int cursor_select_by_word(cursor_t *cursor, int use_srules);
463 int cursor_select_by_word_forward(cursor_t *cursor, int use_srules);
464 int cursor_toggle_anchor(cursor_t *cursor, int use_srules);
465 int cursor_uncut(cursor_t *cursor);
466 
467 // cmd functions
468 int cmd_anchor_by(cmd_context_t *ctx);
469 int cmd_apply_macro_by(cmd_context_t *ctx);
470 int cmd_apply_macro(cmd_context_t *ctx);
471 int cmd_browse(cmd_context_t *ctx);
472 int cmd_close(cmd_context_t *ctx);
473 int cmd_copy_by(cmd_context_t *ctx);
474 int cmd_copy(cmd_context_t *ctx);
475 int cmd_ctag(cmd_context_t *ctx);
476 int cmd_cut_by(cmd_context_t *ctx);
477 int cmd_cut(cmd_context_t *ctx);
478 int cmd_delete_after(cmd_context_t *ctx);
479 int cmd_delete_before(cmd_context_t *ctx);
480 int cmd_delete_word_after(cmd_context_t *ctx);
481 int cmd_delete_word_before(cmd_context_t *ctx);
482 int cmd_drop_cursor_column(cmd_context_t *ctx);
483 int cmd_drop_sleeping_cursor(cmd_context_t *ctx);
484 int cmd_find_word(cmd_context_t *ctx);
485 int cmd_fsearch(cmd_context_t *ctx);
486 int cmd_fsearch_fzy(cmd_context_t *ctx);
487 int cmd_grep(cmd_context_t *ctx);
488 int cmd_indent(cmd_context_t *ctx);
489 int cmd_insert_data(cmd_context_t *ctx);
490 int cmd_insert_newline_above(cmd_context_t *ctx);
491 int cmd_insert_newline(cmd_context_t *ctx);
492 int cmd_insert_tab(cmd_context_t *ctx);
493 int cmd_isearch(cmd_context_t *ctx);
494 int cmd_jump(cmd_context_t *ctx);
495 int cmd_less(cmd_context_t *ctx);
496 int cmd_move_beginning(cmd_context_t *ctx);
497 int cmd_move_bol(cmd_context_t *ctx);
498 int cmd_move_bracket_back(cmd_context_t *ctx);
499 int cmd_move_bracket_forward(cmd_context_t *ctx);
500 int cmd_move_bracket_toggle(cmd_context_t *ctx);
501 int cmd_move_down(cmd_context_t *ctx);
502 int cmd_move_end(cmd_context_t *ctx);
503 int cmd_move_eol(cmd_context_t *ctx);
504 int cmd_move_left(cmd_context_t *ctx);
505 int cmd_move_page_down(cmd_context_t *ctx);
506 int cmd_move_page_up(cmd_context_t *ctx);
507 int cmd_move_relative(cmd_context_t *ctx);
508 int cmd_move_right(cmd_context_t *ctx);
509 int cmd_move_to_line(cmd_context_t *ctx);
510 int cmd_move_until_back(cmd_context_t *ctx);
511 int cmd_move_until_forward(cmd_context_t *ctx);
512 int cmd_move_up(cmd_context_t *ctx);
513 int cmd_move_word_back(cmd_context_t *ctx);
514 int cmd_move_word_forward(cmd_context_t *ctx);
515 int cmd_next(cmd_context_t *ctx);
516 int cmd_noop(cmd_context_t *ctx);
517 int cmd_open_file(cmd_context_t *ctx);
518 int cmd_open_new(cmd_context_t *ctx);
519 int cmd_open_replace_file(cmd_context_t *ctx);
520 int cmd_open_replace_new(cmd_context_t *ctx);
521 int cmd_outdent(cmd_context_t *ctx);
522 int cmd_perl(cmd_context_t *ctx);
523 int cmd_pop_kmap(cmd_context_t *ctx);
524 int cmd_prev(cmd_context_t *ctx);
525 int cmd_push_kmap(cmd_context_t *ctx);
526 int cmd_quit(cmd_context_t *ctx);
527 int cmd_quit_without_saving(cmd_context_t *ctx);
528 int cmd_redo(cmd_context_t *ctx);
529 int cmd_redraw(cmd_context_t *ctx);
530 int cmd_remove_extra_cursors(cmd_context_t *ctx);
531 int cmd_replace(cmd_context_t *ctx);
532 int cmd_save_as(cmd_context_t *ctx);
533 int cmd_save(cmd_context_t *ctx);
534 int cmd_search(cmd_context_t *ctx);
535 int cmd_search_next(cmd_context_t *ctx);
536 int cmd_set_opt(cmd_context_t *ctx);
537 int cmd_shell(cmd_context_t *ctx);
538 int cmd_show_help(cmd_context_t *ctx);
539 int cmd_split_horizontal(cmd_context_t *ctx);
540 int cmd_split_vertical(cmd_context_t *ctx);
541 int cmd_toggle_anchor(cmd_context_t *ctx);
542 int cmd_uncut(cmd_context_t *ctx);
543 int cmd_undo(cmd_context_t *ctx);
544 int cmd_viewport_bot(cmd_context_t *ctx);
545 int cmd_viewport_mid(cmd_context_t *ctx);
546 int cmd_viewport_toggle(cmd_context_t *ctx);
547 int cmd_viewport_top(cmd_context_t *ctx);
548 int cmd_wake_sleeping_cursors(cmd_context_t *ctx);
549 
550 // async functions
551 aproc_t *aproc_new(editor_t *editor, void *owner, aproc_t **owner_aproc, char *shell_cmd, int rw, aproc_cb_t fn_callback);
552 int aproc_set_owner(aproc_t *aproc, void *owner, aproc_t **owner_aproc);
553 int aproc_destroy(aproc_t *aproc, int preempt);
554 int aproc_drain_all(aproc_t *aprocs, int *ttyfd);
555 
556 // uscript functions
557 uscript_t *uscript_run(editor_t *editor, char *path);
558 int uscript_destroy(uscript_t *uscript);
559 
560 // util functions
561 int util_shell_exec(editor_t *editor, char *cmd, long timeout_s, char *input, size_t input_len, int setsid, char *opt_shell, char **optret_output, size_t *optret_output_len);
562 int util_popen2(char *cmd, int setsid, char *opt_shell, int *optret_fdread, int *optret_fdwrite, pid_t *optret_pid);
563 int util_get_bracket_pair(uint32_t ch, int *optret_is_closing);
564 int util_is_file(char *path, char *opt_mode, FILE **optret_file);
565 int util_is_dir(char *path);
566 int util_pcre_match(char *re, char *subject, int subject_len, char **optret_capture, int *optret_capture_len);
567 int util_pcre_replace(char *re, char *subj, char *repl, char **ret_result, int *ret_result_len);
568 int util_timeval_is_gt(struct timeval *a, struct timeval *b);
569 char *util_escape_shell_arg(char *str, int l);
570 int tb_print(int x, int y, uint16_t fg, uint16_t bg, char *str);
571 int tb_printf(bview_rect_t rect, int x, int y, uint16_t fg, uint16_t bg, const char *fmt, ...);
572 int tb_printf_attr(bview_rect_t rect, int x, int y, const char *fmt, ...);
573 void str_append_stop(str_t *str, char *data, char *data_stop);
574 void str_append(str_t *str, char *data);
575 void str_append_len(str_t *str, char *data, size_t data_len);
576 void str_ensure_cap(str_t *str, size_t cap);
577 void str_clear(str_t *str);
578 void str_free(str_t *str);
579 void str_append_replace_with_backrefs(str_t *str, char *subj, char *repl, int pcre_rc, int *pcre_ovector, int pcre_ovecsize);
580 
581 // Globals
582 extern editor_t _editor;
583 
584 // Macros
585 #define MLE_VERSION "1.4.3"
586 
587 #define MLE_OK 0
588 #define MLE_ERR 1
589 
590 #define MLE_PROMPT_YES "yes"
591 #define MLE_PROMPT_NO "no"
592 #define MLE_PROMPT_ALL "all"
593 
594 #define MLE_DEFAULT_TAB_WIDTH 4
595 #define MLE_DEFAULT_TAB_TO_SPACE 1
596 #define MLE_DEFAULT_TRIM_PASTE 1
597 #define MLE_DEFAULT_AUTO_INDENT 0
598 #define MLE_DEFAULT_MACRO_TOGGLE_KEY "M-r"
599 #define MLE_DEFAULT_HILI_BRACKET_PAIRS 1
600 #define MLE_DEFAULT_READ_RC_FILE 1
601 #define MLE_DEFAULT_SOFT_WRAP 0
602 
603 #define MLE_LOG_ERR(fmt, ...) do { \
604     fprintf(stderr, (fmt), __VA_ARGS__); \
605 } while (0)
606 
607 #define MLE_SET_ERR(editor, fmt, ...) do { \
608     snprintf((editor)->errstr, MLE_ERRSTR_SIZE, (fmt), __VA_ARGS__); \
609 } while (0)
610 
611 #define MLE_SET_INFO(editor, fmt, ...) do { \
612     snprintf((editor)->infostr, MLE_ERRSTR_SIZE, (fmt), __VA_ARGS__); \
613 } while (0)
614 
615 #define MLE_RETURN_ERR(editor, fmt, ...) do { \
616     MLE_SET_ERR((editor), (fmt), __VA_ARGS__); \
617     return MLE_ERR; \
618 } while (0)
619 
620 #define MLE_MIN(a,b) (((a)<(b)) ? (a) : (b))
621 #define MLE_MAX(a,b) (((a)>(b)) ? (a) : (b))
622 
623 #define MLE_BVIEW_IS_EDIT(bview) ((bview)->type == MLE_BVIEW_TYPE_EDIT)
624 #define MLE_BVIEW_IS_MENU(bview) ((bview)->is_menu && MLE_BVIEW_IS_EDIT(bview))
625 #define MLE_BVIEW_IS_POPUP(bview) ((bview)->type == MLE_BVIEW_TYPE_POPUP)
626 #define MLE_BVIEW_IS_STATUS(bview) ((bview)->type == MLE_BVIEW_TYPE_STATUS)
627 #define MLE_BVIEW_IS_PROMPT(bview) ((bview)->type == MLE_BVIEW_TYPE_PROMPT)
628 
629 #define MLE_MARK_COL_TO_VCOL(pmark) ( \
630     (pmark)->col >= (pmark)->bline->char_count \
631     ? (pmark)->bline->char_vwidth \
632     : ( (pmark)->col <= 0 ? 0 : (pmark)->bline->chars[(pmark)->col].vcol ) \
633 )
634 
635 #define MLE_COL_TO_VCOL(pline, pcol, pmax) ( \
636     (pcol) >= (pline)->char_count \
637     ? (pmax) \
638     : ( (pcol) <= 0 ? 0 : (pline)->chars[(pcol)].vcol ) \
639 )
640 
641 // Setter macros for kinput structs
642 #define MLE_KINPUT_SET_EX(pi, pfill, pmod, pch, pkey) do { \
643     memset(&(pi), (pfill), sizeof(pi)); \
644     (pi).mod = (pmod); \
645     (pi).ch = (pch); \
646     (pi).key = (pkey); \
647 } while(0)
648 #define MLE_KINPUT_SET(pi, pmod, pch, pkey) MLE_KINPUT_SET_EX(pi, 0x00, pmod, pch, pkey)
649 #define MLE_KINPUT_SET_SPECIAL(pi, pmod)    MLE_KINPUT_SET_EX(pi, 0xff, pmod, 0xffffffff, 0xffff)
650 #define MLE_KINPUT_SET_NUMERIC(pi)          MLE_KINPUT_SET_SPECIAL(pi, 0x40)
651 #define MLE_KINPUT_SET_WILDCARD(pi)         MLE_KINPUT_SET_SPECIAL(pi, 0x80)
652 #define MLE_KINPUT_COPY(pi, pj)             memcpy(&(pi), &(pj), sizeof(pi))
653 
654 #define MLE_LINENUM_TYPE_ABS 0
655 #define MLE_LINENUM_TYPE_REL 1
656 #define MLE_LINENUM_TYPE_BOTH 2
657 
658 #define MLE_PARAM_WILDCARD(pctx, pn) ( \
659     (pn) < (pctx)->loop_ctx->wildcard_params_len \
660     ? (pctx)->loop_ctx->wildcard_params[(pn)] \
661     : 0 \
662 )
663 
664 #define MLE_BRACKET_PAIR_MAX_SEARCH 10000
665 
666 #define MLE_RE_WORD_FORWARD "((?<=\\w)\\W|$)"
667 #define MLE_RE_WORD_BACK "((?<=\\W)\\w|^)"
668 
669 /*
670 TODO PRIORITY
671 [ ] catch ENOSPC
672 [ ] cleanup lua api, e.g., multi-retval
673 [ ] reduce compiler warnings
674 [ ] add cmd_tabulate
675 [ ] add `_free_` hint to (opt)ret vars that need to be freed
676 [ ] finish uscript callbacks
677 [ ] add some sort of syntax checking via hooks
678 [ ] add ## param to page_up/down (by half/third etc)
679 [ ] fix alt/ctrl-enter in prompt inserts newline
680 [ ] replace mark_set_pcre_capture with mark local
681 [ ] fix invalid cli switch should exit(1)
682 [ ] use editor prompt history when bview prompt history is empty
683 TODO BACKLOG
684 [ ] improve isearch kmap (next/prev history)
685 [ ] add option to undo bactions in same loop# as a group
686 [ ] add buffer_repeat
687 [ ] add block select/move
688 [ ] investigate crash when M-e cat'ing huge files
689 [ ] add mark stack (push, move around, pop to go back)
690 [ ] add last cmd status indicator
691 [ ] pass in (bline_t *opt_hint) to buffer_get_ *and start from there instead of first_line
692 [ ] check if buffer exists by inode instead of path
693 [ ] review default key bindings
694 [ ] review use of multi_cursor_code
695 [ ] review use of MLE_RETURN_ERR
696 [ ] move single-use macros out of mle.h
697 TODO REWRITE
698 [ ] rewrite kmap, trie code is hard to read, ** and ## is not elegant, do not use kinput as hash key
699 [ ] rewrite hili code (use_srules sucks; overlapping multi rules bug; test_buffer_srule_overlap.c.todo)
700 [ ] rewrite aproc and menu code
701 [ ] rewrite buffer_set_mmapped to avoid huge mallocs
702 TODO MAYBE
703 [ ] ?allow uscripts to preempt control, use shared uscriptfd
704 [ ] ?add vim emulation mode
705 [ ] ?add refcounting to prevent uscripts from segfaulting
706 [ ] ?make colors, status line, layout configurable
707 [ ] ?add multi-level undo/redo
708 [ ] ?add simple mouse support
709 */
710 
711 #endif
712